Arminair
 
*
Witamy, Gość. Zaloguj się lub zarejestruj. Styczeń 17, 2022, 01:06:14


Zaloguj się podając nazwę użytkownika, hasło i długość sesji


Strony: [1]   Do dołu
  Drukuj  
Autor Wątek: Wstęp do Nasala  (Przeczytany 1288 razy)
0 użytkowników i 1 Gość przegląda ten wątek.
Wojciech Kaczmarski (SP-WKA)
Administrator
*****
Offline Offline

Wiadomości: 96



Zobacz profil
« : Grudzień 04, 2011, 15:00:50 »

Wstęp do języka skryptowego Nasal
autor: SP-WKA

W tym artykule krótko opisze podstawy pisania skryptów w nasalu. Dodatkowo postaram sie wytłumaczyć
jak wstawiać skrypty do odpowiednich plików XML tak, aby 'ożywić' przyciski/dźwignie/kontrolki/etc.
w samolocie. Jeżeli programowałeś/aś kiedys w C, Javie lub Pascalu możesz pominąć część 2,
pamiętaj tylko, że Nasal jest językiem silnie typizowanym.
Skrypty można testować wpisując je w okienku dosttępnym z menu Debug->Nasal console.
Jeżeli masz trochę oleju w głowie to po tym małym 'kursie' powinieneś być w stanie zrobić
naprawdę sporo rzeczy w Nasalu. Oczywiście jeżeli chodzi o usprawnianie samolotów.
Powodzenia!




1. Struktura zmiennych.
Zmienne dotyczące parametrów samolotu w FlightGear (wszystko począwszy od masy samolotu, pozycji
sterów, prędkosci kończąc na kącie natarcia, ilości paliwa itd.) ułożone są w strukturę
przypominającą drzewo. Analogicznie ułożone są foldery i pliki na komputerze. Tutaj odpowiednikiem
pliku jest zmienna. Podejrzeć zmienne możemy wciskając przycisk / w oknie gry. Pojawi sie takie
okienko:

'Internal properties'
Klikając na nazwę przechodzimy dalej, '..' - przejście do 'folderu' wyżej, '.' - przejście
do 'folderu' głównego.
Typy znmiennych jakie możemy tam zobaczyć to: Double (liczba rzeczywista), Int (liczba całkowita)
String (tekst), Bool (wartość logiczna). 'None' oznacza, że zmiennej nie nadano wartości ani typu.


2. Deklaracja zmiennych w skrypcie.
To bardzo proste. Spójrzmy na taki przykład:
Kod:
imie="lechu";
ImiE="leszek";
callsign="SP-LEC";
samolot=777;
Zadeklarowaliśmy cztery zmienne: trzy typu tekstowego - string i jedną Double - liczbę rzeczywistą.
Oczywiście pamiętamy o umieszczeniu średnika na końcu linii. Nazwy zmiennych są 'case sensitive',
oznacza to, że zmienna "imie" i "ImiE" to nie to samo.
Kod:
wysokosc=120.5;
Zmienne wbrew nazwie wcale nie muszą zmieniać wartości, z powodzeniem można je stosować
jako stałe. Typ zmiennej automatycznie dostosowuje się do tego, co wpiszemy po znaku równości.
UWAGA! Symbolem przypisania jest POJEDYNCZY znak równości. Ważne jest,
aby to zapamiętać. Zobaczycie później, dlaczego.


3. Zapis/odczyt zmiennych.
Przypisanie zmiennej wartości można wykonać na dwa sposoby. Jeżeli chcemy zapisać wartość typu
Double lub String, dobrze jest użyć takiej procedury:
Kod:
setprop("/sciezka/do/zmiennej", 123);
setprop("/sciezka/do/innej/zmiennej", "123");
W pierwszej linii mamy zapis do zmiennej znajdującej się w "/sciezka/do/zmiennej". Ustawiamy
jej wartość na 123. Co się okazuje, zmienna jest typu Double. Dalej mamy zapis do innej zmiennej:
ta znajduję się w "/sciezka/do/innej/zmiennej" i nadaliśmy jej wartość 123. Tym razem
zmienna jest typu String, ponieważ wzięliśmy tekst w cudzysłów.
Na konkretnym przykładzie:
Kod:
setprop("/position/altitude-ft", 5000);
Wykonanie tej procedury ustawi nasz samolot na 5000ft.
Drugi sposób, jeżeli chcemy zmiennej nadać inny typ:
Kod:
props.globals.getNode("/aaa/bbb/dobre").setBoolValue(1);
props.globals.getNode("/aaa/bbb/ile").setIntValue(70);
Pierwsza linia nada wartość typu Bool - logicznego (1/0, prawda/fałsz) zmiennej 'dobre' znajdującej
się w "/aaa/bbb/". Analogiczne zadziała druga linia: zmiennej 'ile' nada wartość typu Int - liczba
całkowita. Wartość 70.
Oczywiście zapis o odczyt z/do zmiennych możemy z powodzeniem łączyć ze zmiennymi w srypcie (ale
namieszałem w tym zdaniu). Prosty przykład:
Kod:
wysokosc=10000;
setprop("/position/altitude-ft", wysokosc);
Ten prosty skrypt ustawi nasz samolot na wysokości 10000ft. Proste?

Odczyt wartośći zmiennej:
Kod:
wysokosc=getprop("/position/altitude-ft");
Zmiennej 'wysokosc' nadajemy aktualną wartość wysokości samolotu.

Łączenie zapisu i odczytu:
Powiedzmy że chcemy ustawić nasz samolot na wysokości o 1000ft wyższej od obecnej. W tym przypadku
nie wystarczy już użycie samego zapisania wartości do zmiennej. Przed tym musimy odczytać wartość
aktualną:
Kod:
#sposób 1 (najlepszy):
setprop("/position/altitude-ft", getprop("/position/altitude-ft")+1000);
#                                \-- wpisanie wartosci odczytanej + 1000

#sposób 2:
wysokosc=getprop("/position/altitude-ft")+1000;
setprop("/position/altitude-ft", wysokosc);

#sposób 3:
wysokosc=getprop("/position/altitude-ft");
wysokosc+=1000; #ten zapis oznacza: wysokosc=wysokosc+1000; += to symbol inkrementacji, czyli zwiększenia wartości zmiennej
setprop("/position/altitude-ft", wysokosc);


3. Conditionals, czyli warunki.
Jeżeli chcemy żeby pewna czynność była wykonywana tylko przy określonych warunkach, stosujemy
warunek IF. Powiedzmy, ze chcemy aby jakaś zmienna informowała nas, że lecimy za wysoko:
Kod:
#zadeklarujmy trzy zmienne
teraz=getprop("/position/altitude-ft");
granica=8000;
za_wysoko="nie";

#teraz warunek, jezeli mamy za dużą wysokość
if (teraz>granica){
print("jestesmy za wysoko");
za_wysoko="tak";
}
Komentarz do kodu: warunek po IF należy ZAWSZE umieszczać w nawiasach okrągłych. Przy
wyskości większej od 8000, zmienna za_wysoko przyjmie wartość (typ tekstowy!) "tak" i w konsoli
pojawi się nam napis "jestesmy za wysoko". Funkcja print(); umozliwia wypisanie czegos w konsoli, nie musi to być zmienna testowa. Właściwie każda oprócz Bool jest OK.
Operatorem równości jest == (dwa znaki równości), nierówności słabe oznacza się symbolami
>= i <=, odpowiedno 'mniejsze lub równe', 'większe lub równe'. 'Różne od' to symbol !=. Instrukcje w IF umieszcza się
w nawiasach klamrowych. Pojedynczą instrukcję mozna umieścic bezpośrednio pod warunkiem IF pomijając
nawiasy. Warunek IF może zawierać odczyt ze zmiennej, zmienne i liczby/tekst np.
Kod:
zmienna="jaro";

if (zmienna=="jaro")
print("no siema xD");
Instrukcja print w tym przypadku zostanie wykonana. Warunek jest prawdziwy. Po
nawiasie za IF nie dajemy średnika!
. Bo jebnie.

Łączenie warunków:
Warunki można łączyć operatorami logicznymi OR i AND. OR to suma logiczna, wartosc sumy logicznej jest PRAWDĄ jeżeli choćby jeden z warunków jest prawdziwy:
Kod:
zmienna1="dupa";
zmienna2=999;
zmienna3=0;

if (zmienna1=="zadek" or zmienna2==999 or zmienna3==1)
print("zgadza sie");
Kod w konsoli wypisze "zgadza sie". A czemu? Bo pomimo tego że warunek 1. i 3. dają fałsz, warunek 2. jest prawdziwy. Idąc dalej, AND to iloczyn logiczny, jest prawdziwy tylko gdy wszystkie argumenty są prawdziwe:
Kod:
zmienna1="dupa";
zmienna2=999;
zmienna3=0;

if (zmienna1=="dupa" and zmienna2==999 and zmienna3==1)
print("kaplica");
Ten program nic nie wypisze w onsoli. Ostatni warunek daje FAŁSZ.

Negacja:
Zanegować warunek (odwrócic jego wartosć logiczną) można w ten sposób:
Kod:
if (!(warunek))
...

if (!(a==7 or a==8))
print("a nie jest rowne ani 7 ani 8");
Chodzi o to, aby przed warunkiem/warunkami w nawiasie umieścic wykrzyknik.
Polecana lektura http://pl.wikipedia.org/wiki/Prawa_De_Morgana

Bardziej rozbudowana pętla IF:
Używamy jej gdy chcemy wykonać pewną czynność jeżeli warunek zachodzi, lub inną, gdy nie zachodzi:
Kod:
a=27;

if (a==27)
print("a jest rzeczywiscie rowne 27");
else
print("a nie jest rowne 27");

#szkielet:
if (warunki){
...
...
...
}
else{
...
...
...
}
'else' oznacza 'w przeciwnym wypadku'.


4. Procedury, funkcje.
Procedura to zbiór komend (pewien kod) której nadajemy jakąs nazwę i możemy wywołać w dowolnym
momencie. Przykład:
Kod:
#szkielet:
var NAZWA = func {
...
...
...
}

#deklaracja procedury
var procedurka = func {
a="siema";
print(a);
}

#wywolanie procedury
procedurka();
Skrypt po uruchomieniu nada wartość "siema" (tekst!) zmiennej a i wypisze ją w konsoli.
W procedurach mozemy umieszczać wszystko o czym była mowa wyżej w artykule. Wywołanie procedury oczywiście możemy też wstawić w pętle IF:
Kod:
#deklaracja procedury
var procedurka = func {
a="siema";
print(a);
}

#warunkowe wywolanie procedury
if (jakis_warunek)
procedurka();
Oczywiście zamiast 'jakis_warunek' wstawiamy coś innego.

Procedura setimer();
Dodanie linijki
Kod:
settimer(nazwa, czas);
#nazwa - nazwa procedury, np. procedurka, czas - czas w sekundach
na końcu procedury spowoduje
powtarzanie wywołania procedury co 'czas' sekund. Przyklad:
Kod:
#deklarujemy zmienna
n=0;

#deklarujemy procedure
var liczymy = func {
print(n); #wypisujemy wartosc n
n+=1; #przypominam: n=n+1;
settimer(liczymy, 1);
}

#wywolanie procedury
liczymy();
W konsoli co sekundę zobaczymy nową linię z nową wartością zmiennej n: 0, 1, 2, 3 ...


5. Proste obindowanie przycisku
Do tego rozdziału potrzebny będzie Blender i umiejętność podstaw obsługi.
http://pl.wikipedia.org/wiki/Blender_%28program%29
Do obindowania (przypisania skryptu) do przycisku/pokrętła/niewiemczego trzeba znać nazwę
danego elementu. Nazwę obiektu sprawdzamy importując odpowiedni plik .ac do Blendera, potem
sprawdzając jego nazwę. Warto zauważyć, że do niemal każdego pliku .ac jest dołączony plik
.xml o tej samej nazwie. Niech w naszym przypadku będzie to 'RACT.sw'.
Rodzaje obindowań:
a) zmiana wartości zmiennej na przeciwną (działa z Bool i Int):
Kod:
<animation>
        <type>pick</type>
        <object-name>RACT.sw</object-name>
        <action>
            <button>0</button>
            <repeatable>false</repeatable>
            <binding>
            <command>property-toggle</command>
            <property>/aaa/ract</property>
            </binding>
        </action>
    </animation>
Wytlumaczenie: tag <button> oznacza na jaki przycisk myszy na reagować objekt.
0 - lewy przycisk, 1 - prawy, 3 - rolka do góry, 4 - rolka w dół. <repeatable> oznacza
cykliczne powtarzanie czynności podczas gdy trzymamy wciśnięty przycisk (tutaj false - wyłączone).
<command> może przyjmować różne wartości: 'property-toggle' to zmiana wartości zmiennej
na przeciwną, 'nasal' to uruchomienie skryptu. <property> to ścieżka do zmiennej. W tym
przypadku zmienna 'ract' w /aaa/.
b) skrypt:
Kod:
<animation>
        <type>pick</type>
        <object-name>RACT.sw</object-name>
        <action>
            <button>0</button>
            <repeatable>false</repeatable>
            <binding>
            <command>nasal</command>
            <script>print("nacisnales mnie lewym przyciskiem myszy");</script>
            </binding>
        </action>
    </animation>
Wydaje mi się, że kod nie wymaga wyjaśniania. Dodam tylko, że XML 'nie lubi' symboli
zakazanych: >, <, &. Należy je zamieniać na kolejno: &lt; &gt; &amp;
« Ostatnia zmiana: Grudzień 04, 2011, 17:22:30 wysłane przez SP-WKA » Zapisane
Strony: [1]   Do góry
  Drukuj  
 
Skocz do:  

Powered by SMF 1.1.11 | SMF © 2006-2008, Simple Machines LLC | Sitemap




Polityka cookies
Darmowe Fora | Darmowe Forum

magicaldream wyscigi-smierci forum-olimpijczykow wsbchorzow endercraft