Processing/Zmienne

Z Wikibooks, biblioteki wolnych podręczników.
Przejdź do nawigacji Przejdź do wyszukiwania

Pamięć bywa zawodna[edytuj]

Nie ma co ukrywać - pamięć ludzka jest świetna, lecz niezwykle krótkotrwała. Pisząc nasze programy często będziemy zapominać, co jest czym i skąd wzięło się akurat tutaj. Dlatego nasz kod wypełniony jest komentarzami, dlatego również nazwy funkcji (choć w języku angielskim) są proste i oznaczają to, co robią. Funkcje funkcjami, ale co z tamik przykładem?


 1 size( 400, 400 );
 2 background( 255, 230, 230 );
 3 smooth();
 4 
 5 noStroke();
 6 fill( 250, 200, 200 );
 7 
 8 // kolo w centrum okna 
 9 // o wielkosci jednej czwartej szerokosci okna
10 ellipse( 200, 200, 100, 100 );


Plik:Processing R-03 01.png


Łatwo się domyśleć, że kółko o średnicy jednej czwartej szerokości okna narysowane jest w połowie długości i połowie szerokości tego okna. Wszystko gra. Ale czy nie lepiej byłoby tak?


 1 size( 400, 400 );
 2 background( 255, 230, 230 );
 3 smooth();
 4 
 5 noStroke();
 6 fill( 250, 200, 200 );
 7 
 8 // kolo w centrum okna 
 9 // o wielkosci jednej czwartej szerokosci okna
10 ellipse( width / 2, height / 2, width / 4, width / 4 );


Teraz od razu wiadomo, że chodziło mi o koło wielkości jednej czwartej szerokości okna i znajdujące się w jego środku. To coś trochę innego niż koło o wielkości 100x100 i położeniu 200x200.

Zmieniaj raz, zmieniaj wszędzie[edytuj]

Spójrzmy na ten przykład raz jeszcze - tym razem jednak zmienimy wielkość okna z 400x400 na 500x300:


 1 size( 500, 300 );
 2 background( 255, 230, 230 );
 3 smooth();
 4 
 5 noStroke();
 6 fill( 250, 200, 200 );
 7 
 8 // kolo w centrum okna 
 9 // o wielkosci jednej czwartej szerokosci okna
10 ellipse( width / 2, height / 2, width / 4, width / 4 );


Processing R-03 02.png


Jak widać nasz fragment kodu wciąż możemy przeczytać w taki sam sposób:


1 Koło w połowie szerokości, w połowie wysokości o średnicy jednej czwartej szerokości okna


To właśnie jest ta różnica w znaczeniu między "200x200" a "W centrum okna". Czym więcej w naszym programie znaczących i zrozumiałych treści, tym lepiej dla nas i samego programu.

Zmienne...[edytuj]

Tak samo, jak wielkość szerokości okna zapisać możemy jako width, tak samo zapisać możemy dowolną wartość, z której korzystać będziemy w naszym programie. Jak to działa? Wyobraźmy sobie taki przykład:


 1 size( 500, 300 );
 2 background( 255 );
 3 smooth();
 4 
 5 // wielkosc kola
 6 int circleSize = 100;
 7 
 8 // duze kolo
 9 ellipse( width / 2, height / 2, circleSize, circleSize );
10 
11 // male kolo
12 ellipse( width / 2, height / 2, circleSize / 2, circleSize / 2 );


Dzięki wprowadzeniu specjalnej nazwy (circleSize, czyli wielkość koła), która w naszym programie zastępuje wartość 100 z daleka widzimy, że drugie kółko będzie o połowę mniejsze od pierwszego, a do tego, jeśli przyjdzie nam zmienić wielkość obu kół wystarczy zrobić to raz w jednym miejscu. Znów zatem dotykamy tego samego rozróżnienia między tym, co znaczy "dwa koła o średnicach - odpowiednio - 100 i 50 pikseli", a tym, co znaczy "dwa koła - jedno o połowę mniejsze od drugiego". To ważna różnica, na którą warto zwracać uwagę.

...i ich typy[edytuj]

W powyższym fragmencie kodu nasza zmienna (circleSize) poza nazwą oraz przypisaną jej wartością (100) posiada również dodatkową informację na temat swojego typu reprezentowaną przez słowo int (od angielskiego integer, czyli liczba całkowita). Takie oznaczenie typu jest w Processingu konieczne, żeby programowi łatwiej było zorganizować sobie pamięć operacyjną komputera. Co to jednak oznacza dla nas, programistów? Przede wszystkim to, że musimy każdej zmiennej nadać typ (jak choćby int) oraz przestrzegać własnej deklaracji. Jeśli tworzymy zmienną typu całkowitego to nie możemy przypisać jej ułamka:


1 int x = 3.14;  //  B Ł Ą D ! ! !
2 int y = 3;     //  D O B R Z E

Co mamy do wyboru[edytuj]

Typów zmiennych w Processingu jest kilkanaście. Niektóre z nich są proste, jak int, inne bardzo złożone jak PImage (odpowiedzialny za pracę z obrazkami - dojdziemy do tego). Trzy podstawowe typy, z których będziemy korzystali na początku to:


1 int x = 1;                         // liczby całkowite
2 float y = 3.14;                    // liczby z przecinkiem
3 color c = color( 200, 100, 100 );  // kolor - w tym przypadku odcień czerwieni


Pierwsze dwa typy są proste i na razie nie musimy się na ich temat rozpisywać (przyjdzie na to pora, jak będziemy pisali o pamięci operacyjnej i bardziej zaawansowanej pracy z kolorami i obrazem). Teraz przyjrzyjmy sie zmiennej typu color.

color[edytuj]

Zmienna typu color może przechowywać dla nas informację o kolorze. To coś jak puszka z farbą:


 1 size( 400, 300 );
 2 
 3 background( 255, 230, 230 );
 4 smooth();
 5 
 6 int circleSize = 100;
 7 int horizontalCenter = width / 2;
 8 int verticalCenter = height / 2;
 9 
10 color darkColor = color( 100, 50, 50 );
11 color lightColor = color( 250, 200, 200 );
12 
13 noStroke();
14 fill( darkColor );
15 ellipse( horizontalCenter, verticalCenter, circleSize, circleSize );
16 
17 fill( lightColor );
18 ellipse( horizontalCenter, verticalCenter, circleSize / 2, circleSize / 2 );
19 
20 ellipse( width, verticalCenter, circleSize / 4, circleSize / 4);
21 
22 fill( darkColor );
23 ellipse( 0, verticalCenter, circleSize, circleSize );


Processing R02 04.png


Nie trzeba znać się na programowaniu, by od razu widzieć, która część kodu odpowiada za rysowanie których elementów na ekranie. Najpierw rysujemy ciemne (darkColor) i duże (circleSize) koło (linia 15), później jasne (lightColor) i małe (circleSize / 2) na wierzchu (linia 18), następnie to po prawej (linia 20), a na końcu to po lewej (linia 23). Wyraźnie też widać, jak korzystamy z naszych zmiennych typu color - w liniach 14, 17 i 22 wybieramy nową puszkę z farbą i malujemy nią kolejne koła.

Kto razem, kto osobno[edytuj]

Przyjrzyjmy się fragmentom powyższego kodu w dwóch wersjach:


 1 // omijamy wielkość okna i inne deklaracje
 2 
 3 // kola w centrum
 4 fill( darkColor );
 5 ellipse( horizontalCenter, verticalCenter, circleSize, circleSize );
 6 fill( lightColor );
 7 ellipse( horizontalCenter, verticalCenter, circleSize / 2, circleSize / 2 );
 8 
 9 // kola po bokach
10 ellipse( width, verticalCenter, circleSize / 4, circleSize / 4);
11 fill( darkColor );
12 ellipse( 0, verticalCenter, circleSize, circleSize );

oraz

// omijamy wielkość okna i inne deklaracje

// ciemne kola
fill( darkColor );
ellipse( horizontalCenter, verticalCenter, circleSize, circleSize );
ellipse( 0, verticalCenter, circleSize, circleSize );

// jasne kola
fill( lightColor );
ellipse( horizontalCenter, verticalCenter, circleSize / 2, circleSize / 2 );
ellipse( width, verticalCenter, circleSize / 4, circleSize / 4);


Jak widać ten sam kod pogrupowaliśmy w dwa różne sposoby i choć efekt wizualny jest taki sam, to zupełnie inaczej czyta się oba fragmenty. Ciężko określić, który z nich jest lepszy - to z jednej strony sprawa gustu programisty, z drugiej większego kontekstu programu. Ważne jest jednak, by pamiętać o dobrej, czytelnej i znaczącej organizacji kodu źródłowego, bo programy, które będziemy pisali w przyszłości mogą mieć kilkaset lub nawet kilka tysięcy linii kodu źródłowego i wtedy logiczna organizacja to podstawa.

Wracamy do coloru[edytuj]

Pisaliśmy, że zmienne typu kolor przechowują informację o kolorze i że przypisujemy im wartość w następujący sposób:


1 color black = color( 0 ); // czarny
2 color white = color( 255 ); // bialy
3 color lightRed = color( 255, 230, 230 );  // jasny czerwony
4 color niceGrey = color( 80, 80, 80 );  // fajny szary
5 color nicerGrey = color( 50 );  // jeszcze fajniejszy szary


Co jednak, gdybyśmy chcieli nasz lightRed zrobić nieco ciemniejszym? Mamy na to dwie metody:


1 color lightRed = color( 255, 230, 230 );  // jasny czerwony
2 lightRed = color( 200, 150, 150 );  nowy, trochę ciemniejszy czerwony

lub

1 color lightRed = color( 255, 230, 230 );  // jasny czerwony
2 float r = red( lightRed );
3 float g = green( lightRed );
4 float b = blue( lightRed );
5 
6 lightRed = color( r - 55, g - 80, b - 80 );


Pierwszy fragment jest prosty i wymaga wyjaśnienia tylko jednej rzeczy: w każdym programie zmienne deklarowane są tylko raz! To znaczy, że w pierwszej linii kodu występuje deklaracja typu color, a w drugiej nie, bo Processing wie już, że lightRed jest zmienną typu color - po prostu przypisujemy jej nową wartość za pomocą funckji color( int r, int g, int b ).
W drugim fragmencie dzieje się więcej, bo mamy kilka dodatkowych zmiennych oraz wykorzystujemy funkcje red( color c ), green( color c ), blue( color c ), które pozwalają nam na wydobycie informacji o trzech składowych danego koloru c. Moglibyśmy zapisać go następująco:


 1 tworzę zmienną:
 2   zmienna typu kolor --> lightRed
 3   lightRed --> jasno czerwony ( RGB: 255, 230, 230 )
 4 
 5 tworzę zmienną:
 6   zmienna typu ułamkowego --> r
 7   r --> ilość czerwieni w lightRed
 8 
 9 tworzę zmienną:
10   zmienna typu ułamkowego --> g
11   g --> ilość zieleni w lightRed
12 
13 tworzę zmienną:
14   zmienna typu ułamkowego --> b
15   b --> ilość niebieskiego w lightRed
16 
17 przypisuję wartość:
18   tworzę nowy kolor --> R: wartość r minus 55, G: wartość g minus 80, B: wartość b minus 80
19   lightRed --> nowy kolor ( RGB: 200, 150, 150 )


Nic skomplikowanego, a pozwala nam się dostać do składowych koloru, co moglibyśmy wykorzystać np. tak:


 1 size( 400, 300 );
 2 
 3 background( 255, 230, 230 );
 4 smooth();
 5 
 6 int circleSize = 100;
 7 int horizontalCenter = width / 2;
 8 int verticalCenter = height / 2;
 9 
10 color lightRed = color( 255, 230, 230 );  // jasny czerwony
11 float r = red( lightRed );
12 float g = green( lightRed );
13 float b = blue( lightRed );
14 
15 color middleRed = color( r / 2, g / 2, b / 2 ); // sredni kolor: polowa wszystkich wartosci z lightRed
16 color darkRed = color( r / 3, g / 3, b / 3 ); // ciemny kolor: jedna trzecia wszystkich wartosci z lightRed
17 
18 noStroke();
19 fill( darkRed );
20 ellipse( horizontalCenter, verticalCenter, circleSize, circleSize );
21 
22 fill( middleRed );
23 ellipse( horizontalCenter, verticalCenter, circleSize / 2, circleSize / 2 );
24 
25 fill( lightRed );
26 ellipse( horizontalCenter - ( circleSize / 2 ), verticalCenter, circleSize / 3, circleSize / 3 );
27 ellipse( horizontalCenter, verticalCenter, circleSize / 4, circleSize / 4 );
28 ellipse( horizontalCenter + ( circleSize / 2 ), verticalCenter, circleSize / 3, circleSize / 3 );


Processing R03 04.png


Słowo o przyjaźni[edytuj]

Zmiennych będziemy używali do końca podręcznika w literalnie każdym programie, więc wszelkie niejasności wyjdą w praniu. Wrócimy do nich również, w rozdziale poświęconym Javie i programowaniu obiektowemu. Zmienne bowiem, to jeden z przyjaciół programisty.