2009.08_Język skryptowy Lua _[Jezyki Programowania].pdf

(703 KB) Pobierz
441671625 UNPDF
Języki programowania
Język skryptowy Lua
Charakterystyka i rola języka skryptowego
Lua w programowaniu gier (i nie tylko)
Lua jest jednym z najczęściej wykorzystywanych języków skryptowych
w programowaniu gier komputerowych. Skrypty często służą implementacji
algorytmów logiki gry, SI czy interface'u użytkownika, co ułatwia modyfikację
i rozbudowę aplikacji. Przyjrzymy się charakterystyce języka Lua oraz
integracji skryptów Lua w aplikacjach takich jak gry komputerowe.
Dowiesz się:
• Co to jest Lua;
• Jak praktycznie korzystać z Lua.
Powinieneś znać:
• Podstawy programowania w C/C++;
• Filozoię języków skryptowych.
rycznych lub znaku _ , jednak nie mogą roz-
poczynać się cyfrą. Istnieją również słowa za-
strzeżone, tj. and , or , break , else itp., któ-
re nie mogą opisywać identyfikatorów. Lua
rozróżnia wielkość liter, zatem for oznacza
pętlę, natomiast For widziany jest jako iden-
tyfikator. Podwójny myślnik -- rozpoczyna
komentarz i ignoruje na etapie kompilacji/
wykonywania wszystkie znaki występujące
po nim aż do końca linii. Istnieje również
możliwość zakomentowania całego bloku
składającego się z kilku linii poprzez --[["
i "]] .
Poziom
trudności
Pascal) z bardziej złożonymi konstrukcjami
opisu danych opartych na tablicach asosja-
cyjnych, a także rozszerzalną semantyką.
Lua jest projektem open-source'owym, za-
implementowanym w C zgodnie ze stan-
dardami ANSI C, którego głównym celem
jest łatwość użycia, prostota, wydajność i
przenośność kodu.
Niniejszy artykuł ma na celu przybliże-
nie czytelnikowi, poprzez liczne przykłady,
charakterystyki języka Lua, oraz wskazanie
praktycznych aspektów wykorzystania ję-
zyków skryptowych w aplikacjach kompu-
terowych.
Na początku omówimy podstawowe
elementy składni języka Lua, a następ-
nie przejdziemy do integracji skryptów z
aplikacjami napisanymi w C/C++. Zapo-
znamy się również z wbudowanymi stan-
dardowymi bibliotekami Lua ułatwiają-
cymi pisanie bardziej skomplikowanych
skryptów.
J ęzyki skryptowe to języki programo-
wania umożliwiające rozszerzanie
funkcjonalności aplikacji komputero-
wych bez konieczności zmiany kodu wyni-
kowego. Są one również intensywnie wyko-
rzystywane przy automatyzacji działań ad-
ministracyjnych systemu, np. w powłoce
systemu Unix. Głównym założeniem te-
go typu języków jest możliwość ingeren-
cji użytkownika w istniejący i działający
system bez znajomości kodu źródłowego.
Przykładami takich języków są Bash, Py-
thon, Perl, PHP, QuakeC, GameMonkey,
UnrealScript oraz Lua.
Języki skryptowe często wykorzystywa-
ne są w procesie tworzenia gier kompute-
rowych w celu sterowania przebiegiem fa-
buły (np. misje, dialogi), podejmowania
decyzji w algorytmach sztucznej inteligen-
cji (np. sterowanie postaciami NPC, ang.
non-playable characters ) czy też graficznej
obsługi interfejsu gry (GUI, ang. graphical
user interface ). Jednym z najczęściej wybie-
ranych przez twórców gier języków skrypto-
wych jest język Lua, który został użyty w ty-
tułach takich jak: Crysis, FarCry, Baldur's
Gate, S.T.A.L.K.E.R., Wiedźmin czy World
of Warcraft.
Lua jest lekkim językiem skryptowym łą-
czącym ze sobą elementy prostego języka
proceduralnego (składnia podobna do języka
Typy i wyrażenia
W Lua nie deklarujemy typów zmiennych
– każda zmienna ma dynamiczny typ okre-
ślany przez jej wartość.
Istnieje 8 podstawowych typów danych
w Lua:
nil – przyjmuje jedną wartość nil , któ-
ra określa brak konkretnej wartości (czę-
sto nil jest stosowany do określenia
zmienną niezainicjalizowaną);
boolean – przyjmuje standardowe
wartości boolowskie, czyli true lub
false ;
number – liczba reprezentująca war-
tości rzeczywiste (zmiennoprzecinko-
we); liczby możemy zapisywać na róż-
ne sposoby, np.: 18, 3.141592, 1.23e12,
4.18e-3;
string – standardowy łańcuch znaków,
np. " What is your name? ";
userdata – typ danych umożliwiający
przetrzymywanie dowolnych danych z
języka C (np. wskaźników) w struktu-
rach Lua;
function – funkcje zdefniniowane ja-
ko wykonywalny ciąg instrukcji; funk-
cje mogą być deklarowane wewnątrz
innych funcji, mogą być argumentami
Opis języka – podstawy
Jak przekonamy się w dalszej części tekstu,
składnia Lua jest zwięzła i intuicyjna dla
każdego, kto miał jakąkolwiek styczność z
językami programowania.
Najczęściej przygodę z nowym językiem
programowania rozpoczyna się od napi-
sania najprostszego programu typu 'hello
world'. Taki program w Lua przedstawio-
no w Listingu 1.
Konwencje leksykalne
Identyfikatory w Lua mogą składać się z
dowolnego łańcucha znaków alfanume-
46
08/2009
441671625.042.png 441671625.043.png 441671625.044.png 441671625.045.png 441671625.001.png 441671625.002.png 441671625.003.png 441671625.004.png 441671625.005.png 441671625.006.png
Język skryptowy Lua
innych funkcji, lub być zwracane z in-
nej funkcji;
thread – wątek w Lua – z uwagi na cha-
rakter niniejszego artykułu nie będzie-
my omawiać wątków w Lua;
table – tablica asosjacyjna będąca naj-
cięższym orężem Lua; dokładny opis ta-
blic znajduje się w dalszej części.
przez kolekcję par (klucz, wartość), gdzie
kluczem może być wszystko poza war-
tością nil. Elementami tablicy mogą być
wszystkie wartości podstawowych typów
Listing 1. Program typu 'hello world' w Lua wraz z przykładem komentarzy
-- irst.lua
print ( "Hello from Lua!" );
--[[
Przykład komentarza
umieszczonego w kilku liniach
]]
W dowolnym miejscu skryptu możemy
sprawdzić typ danej zmiennej poleceniem
type (jak pokazano w Listingu 2).
Lua, jak przystało na porządny język pro-
gramowania, oferuje również różnego rodza-
ju operatory do definiowania wyrażeń. Wy-
różniamy:
Listing 2. Sprawdzanie typu zmiennych w Lua
print ( type ( a )) --> nil (zmienna 'a' nie została zainicjalizowana)
a = 10
print ( type ( a )) --> number
a = "string test"
print ( type ( a )) --> string
a = print -- a staje się funkcją print
a ( type ( a )) --> function
• operatory arytmetyczne, czyli + (doda-
wanie), - (odejmowanie), * (mnożenie),
/ (dzielenie), % (modulo) i ^ (potęgowa-
nie);
• operatory porównania, czyli == (rów-
ne), ~= (różne), < (mniejsze), > (większe),
<= (mniejsze lub równe), >= (większe lub
równe);
• operatory logiczne, takie jak and (część
wspólna), or (suma logiczna), not (negacja).
Listing 3. Przykład pętli, funkcji i instrukcji warunkowych
-- wyznaczanie wartości minimalnej i maksymalnej
min_max = function ( a , b , c )
local tab = { a , b , c };
local idx_min = 1 ;
local idx_max = 1 ;
for i = 2 , 3 do
if tab [ i ] < tab [ idx_min ] then idx_min = i ; end ;
if tab [ i ] > tab [ idx_max ] then idx_max = i ; end ;
end ;
return tab [ idx_min ], tab [ idx_max ];
end ;
print ( min_max ( 1 , 8 , 3 )); --> 1 8
-- rozwiązywanie równania kwadratowego
quadratic_eq = function ( a , b , c )
delta = b * b - 4 * a * c ;
if delta > 0 then
sqr_delta = math.sqrt ( delta );
x0 = ( - b - sqr_delta ) / ( 2 * a );
x1 = ( - b + sqr_delta ) / ( 2 * a );
return x0 , x1 ;
elseif delta == 0 then
x = - b / ( 2 * a );
return x , x ;
else
return nil , nil ;
end ;
end ;
print ( quadratic_eq ( 1 , - 1 , - 2 )); --> -1 2
Instrukcje i funkcje
Lua obsługuje standardowy zestaw instruk-
cji podobnych do tych stosowanych w języku
Pascal czy C. Istnieje możliwość definiowa-
nia bloków instrukcji objętych słowami klu-
czowymi do i end , które można kontrolować
poprzez break czy return . Na listę pojedyn-
czych instrukcji składają się:
• instrukcje przypisania = ;
• instrukcje warunkowe, if / elseif / else /
end ;
• pętle, for / do / end , while / do / end , repeat /
until /;
• wywołania funkcji;
• lokalne deklaracje zmiennych.
Instrukcja przypisania może dotyczyć kil-
ku zmiennych. Pojedyncze instrukcje mogą
opcjonalnie kończyć się średnikiem.
Listing 3 ilustruje wykorzystanie funkcji,
zastosowanie pętli oraz instrukcji warunko-
wych na przykładzie funkcji wyznaczającej
wartość minimalną i maksymalną z trzech
liczb, oraz funkcji obliczającej pierwiastki
równania kwadratowego.
Jak widzimy w przykładzie, funkcje mo-
gą przyjmować i zwracać więcej niż jeden
parametr. Istnieje również możliwość de-
klarowania funkcji rekurencyjnych (Li-
sting 4).
Listing 4. Przykład funkcji rekurencyjnej w Lua
-- obliczenie n!
function factorial ( n )
if n == 1 then
return 1 ;
else
return n * factorial ( n - 1 );
end
end
-- obliczenie 5!
print ( factorial ( 5 )); --> 120
Tablice
Tablice są najistotniejszymi struktura-
mi danych w Lua. Są one reprezentowane
www.sdjournal.org
47
441671625.007.png 441671625.008.png 441671625.009.png 441671625.010.png 441671625.011.png 441671625.012.png 441671625.013.png 441671625.014.png 441671625.015.png 441671625.016.png 441671625.017.png
Języki programowania
Lua, czyli także same tablice. Dzięki te-
mu mechanizm tablicy umożliwia definio-
wanie użytkownikowi dowolnych struktur
danych, które mogą być utożsamiane z ele-
mentami takimi jak: lista , wektor , kolejka ,
zestaw czy stos .
W tradycyjnych językach programowania
jakimi są C czy Pascal w większości przypad-
ków złożone struktury danych reprezento-
wane są właśnie przez dynamiczne listy lub
wektory prostych typów danych. Tablice w
Lua umożliwiają implementację o wiele bar-
dziej złożonych i elastycznych struktur, stwo-
rzonych specjalnie na potrzeby rozwiązania
danego zagadnienia. Listing 5 pokazuje przy-
kłady wykorzystania tablic w Lua realizując
proste zbiory danych, listę jednokierunko-
wą, czy strukturę zawierającą zarówno atry-
buty jak i metody.
Listing 5. Przykłady wykorzystania tablicy w Lua
-- prosty wektor liczb
squares = { 1 , 4 , 9 , 16 , 25 , 36 , 49 , 64 , 81 }
-- zbiór danych
creature = { name = "Ghoul" , health = 100 }
print ( creature [ "name" ]); --> Ghoul
print ( creature . name ); --> Ghoul
-- lista
list = nil ;
list = { next = list , value = 2 };
list = { next = list , value = "test" };
list = { next = list , value = math.pi };
Integracja z C++
Po zapoznaniu się z podstawowymi ele-
mentami języka skryptowego Lua przejdź-
my do jego praktycznego zastosowania w
aplikacjach napisanych w C++. Listing 6
obrazuje kompletny kod programu w C++,
którego celem jest poprawne zainicjalizo-
wanie maszyny wirtualnej i wykonanie
skryptu Lua.
W pierwszym rzędzie należy dołączyć na-
główki Lua ( lua.h , lualib.h i lauxlib.h ) oraz
skompilowaną bibliotekę Lua (w przykła-
dzie jest to lua51.lib ). Binarną wersję biblio-
teki musimy sobie sami zbudować ze źró-
deł Lua, lub skorzystać z gotowej skompilo-
wanej wersji umieszczonej na stronie domo-
wej projektu.
Następnie poleceniem lua_open() two-
rzymy maszynę wirtualną ( lua_State ) i
rejestrujemy standardowe biblioteki opi-
sane w dalszej części artykułu. Teraz mo-
żemy już wykonać skrypt poleceniem
luaL_dofile() , sprawdzając jednocze-
śnie, czy skrypt nie zawiera błędu (np.
składniowego). Na zakończenie program
zwalnia maszynę wirtualną poleceniem
lua_close() .
Wiemy już, jak wykonać skrypt na maszy-
nie wirtualnej Lua z poziomu kodu aplika-
cji w C++. W powyższym przykładzie bra-
kuje jednak symbiozy pomiędzy aplikacją a
skryptem – każdy z tych procesów wykonu-
je się dla samego siebie . Musimy zatem stwo-
rzyć mechanizm komunikacji pomiędzy apli-
kacją a skryptem.
Mechanizmem umożliwiającym sterowa-
nie naszą aplikacją jest zarejestrowanie funk-
cji aplikacji w maszynie wirtualnej Lua, któ-
ra jest punktem łączącym obydwa proce-
sy. Załóżmy, że chcemy udostępnić maszy-
nie wirtualnej funkcję aplikacji, która przyj-
muje dwie liczby i łańcuch znaków jako pa-
rametry wejściowe i dodatkowo zwraca wy-
nik. Funkcję w naszej aplikacji zamieściliśmy
w Listingu 7.
W pierwszej fazie pobieramy argumenty
funkcji, odwołując się do elementów na sto-
sie względem jego wierzchołka (wywołanie
funkcji w Lua powoduje wrzucenie wszyst-
ptr = list ;
while ptr do
print ( ptr . value );
ptr = ptr . next ;
end ; --> 3.141592 test 2
-- struktura/klasa
Vec3 = {};
Vec3 . new = function ( x , y , z )
return { x = x , y = y , z = z , length = function () return math.sqrt ( x * x + y * y + z * z ) end ;}
end ;
v = Vec3 . new ( 4 , 2 , 4 );
print ( v : length ()); --> 6
Listing 6. Inicjalizacja maszyny wirtualnej i wykonanie skryptu Lua
#include <iostream>
/// dołączenie nagłówków Lua
extern "C"
{
#include "lua.h"
#include "lualib.h"
#include "lauxlib.h"
}
/// dołączenie biblioteki Lua
#pragma comment (lib, "lua51.lib")
/// program główny
int main ()
{
/// stworzenie maszyny wirtualnej Lua
lua_State * s = lua_open ();
/// inicjalizacja standardowych bibliotek
luaL_openlibs ( s );
/// wykonanie skryptu Lua
if ( luaL_doile ( s , "sdj.lua" ))
{
/// błąd
std :: cout << "Error while running script: " << lua_tostring ( s , - 1 ) << std ::
endl ;
return 1 ;
}
/// zamknięcie maszyny wirtualnej
lua_close ( s );
return 0 ;
}
48
08/2009
441671625.018.png 441671625.019.png 441671625.020.png 441671625.021.png 441671625.022.png 441671625.023.png 441671625.024.png
 
Język skryptowy Lua
kich argumentów na stos w kolejności zgod-
nej z porządkiem parametrów funkcji). Za-
tem wywołanie funkcji postaci Foo(n0 , n1 ,
op ) spowoduje sytuację na stosie zobrazowa-
ną na Rysunku 1.
Po pobraniu argumentów ze stosu wyko-
nujemy przykładowe operacje (dodawanie
lub mnożenie) w zależności od trzeciego
parametru przekazanego do funkcji. Wy-
nik operacji wrzucamy na stos – w przy-
padku nierozpoznanej operacji wrzucamy
wartość nil . Ostatnie polecenie return 1
oznacza, iż zwracamy jedną wartość z na-
szej funkcji.
Mając zdefiniowaną funkcję na pozio-
mie aplikacji, rejestrujemy ją poleceniem
lua_register(s, "Foo", FooFunc) – oczy-
wiście przed wykonaniem skryptu. Parame-
try lua_register oznaczają odpowiednio:
stworzoną maszynę wirtualną Lua, odpo-
wiednik nazwy funkcji w Lua oraz nazwę
funkcji statycznej w C, którą rejestrujemy.
Teraz już wszystko gotowe, aby odwołać się
do naszej funkcji aplikacji z poziomu skryp-
tu – Listing 8.
Znamy już sposób odwoływania się do
funkcji aplikacji z poziomu skryptu Lua – te-
raz spróbujemy zrobić to samo w drugą stro-
nę. Wcześniej w przykładach pokazaliśmy
funkcję factorial() do obliczania silni. Zo-
baczmy, jak ponownie wykorzystać ideę sto-
sowej maszyny wirtualnej i zawołać funk-
cję skryptową z poziomu kodu aplikacji (Li-
sting 9).
Zaczynamy od wrzucenia na szczyt sto-
su funkcji factorial() z globalnej tablicy
Lua. Jeżeli operacja powiodła się (wartość
na szczycie stosu jest różna od nil), wrzuca-
my kolejno argumenty funkcji (w naszym
przypadku jest to jedna liczba – w przykła-
dzie jest to 4).
W ten sposób mamy przygotowane wy-
wołanie funkcji, które wykonujemy polece-
niem lua_call , podając liczbę parametrów
wołanej funkcji (jeden) i liczbę zwracanych
wartości przez funkcję (również jeden).
Ostatnim krokiem jest pobranie ze szczy-
tu stosu wyniku działania funkcji i wypisa-
nia go na ekran.
ra wiąże się z odgrywaniem różnych dźwię-
ków, generowania efektów specjalnych czy
przyznawania punktów graczowi w zależ-
ności od tego, w co uderzyła piłeczka. W
tym celu przy każdej kolizji piłeczki z kloc-
kami na planszy będziemy wołać funkcję ze
skryptu Lua.
W pierwszej kolejności musimy przy-
gotować odpowiedni kod aplikacji, któ-
ry obsługuje zderzenia piłeczki z innymi
obiektami. Po wykryciu zderzenia będzie-
my wołać funkcję skryptu Lua, który po-
dejmie odpowiednią akcję, bazując na in-
formacji o zderzeniu. W naszym prostym
przykładzie na tę informację będą składały
się: nazwa typu klocka uderzonego przez
piłeczkę i pozycja piłeczki na ekranie (Li-
sting 10).
Nasza gra sprawdza, czy nastąpiło zde-
rzenie piłeczki z klockiem na planszy
( IsCollision() ). Jeżeli tak, to wypełnia-
na jest odpowiednia struktura z informacją
o zderzeniu, a następnie wołana jest funk-
cja OnCollision() ze skryptu Lua. Nale-
ży oczywiście uprzednio przygotować ar-
gumenty tej funkcji – w naszym przypad-
ku będzie to tablica z elementami opisu-
jącymi nazwę klocka i pozycję piłeczki na
Listing 7. Przygotowanie funkcji aplikacji dla skryptu Lua
static int FooFunc ( lua_State * s )
{
/// pobierz pierwszy argument
loat n0 = ( loat ) lua_tonumber ( s , - 3 );
/// pobierz drugi argument
loat n1 = ( loat ) lua_tonumber ( s , - 2 );
/// pobierz trzeci argument
std :: string op = lua_tostring ( s , - 1 );
loat res = 0.0f ;
if ( op == "add" )
res = n0 + n1 ;
else if ( op == "mul" )
res = n0 * n1 ;
else
{
lua_pushnil ( s );
return 1 ;
}
/// wrzuć wynik na szczyt stosu
lua_pushnumber ( s , res );
/// 1 oznacza liczbę zwracanych wartości
return 1 ;
}
Listing 8. Wywołanie funkcji aplikacji ze skryptu
print ( Foo ( 10 , 14 , "mul" )); --> 140
print ( Foo ( 10 , 14 , "add" )); --> 24
print ( Foo ( 10 , 14 , "div" )); --> nil
Listing 9. Wywołanie funkcji skryptu z kodu aplikacji
/// pobranie funkcji z globalnej tablicy skryptu
lua_getglobal ( s , "factorial" );
if ( ! lua_isnil ( s , - 1 ))
{
/// wrzucenie na stos argumentu funkcji
lua_pushnumber ( s , 4 );
/// zawołanie funkcji
lua_call ( s , 1 , 1 );
/// wyświetlenie wartości zwróconej
std :: cout << "Result from script function: " << lua_tonumber ( s , - 1 ) << std ::
endl ;
Praktyczne zastosowanie Lua
W poprzedniej części pokazaliśmy, w ja-
ki sposób można zrealizować obustron-
ną komunikację pomiędzy skryptem a ko-
dem aplikacji. Spróbujmy teraz odnieść się
do tych informacji poprzez praktyczne za-
stosowanie skryptu w konkretnym progra-
mie. Załóżmy, że tworzymy prostą grę ty-
pu arkanoid, gdzie zadaniem gracza jest
odbijanie piłeczki paletką tak, aby zbija-
ła one konkretne klocki ułożone na plan-
szy. Chcemy umożliwić (spoza kodu apli-
kacji) pełną kontrolę zbijania klocków, któ-
}
www.sdjournal.org
49
441671625.025.png 441671625.026.png 441671625.027.png 441671625.028.png 441671625.029.png 441671625.030.png 441671625.031.png 441671625.032.png 441671625.033.png 441671625.034.png
Języki programowania
ekranie. Powyższy kod pokazuje, jak stwo-
rzyć i przekazać do maszyny wirtualnej ta-
blicę postaci event= {block = "name",
x=0, y=0} (oczywiście wypełnioną odpo-
wiednimi wartościami). Przykładowa funk-
cja OnCollision(event) po stronie skryp-
tu może wyglądać jak pokazano w Listin-
gu 11.
Funkcja sprawdza, z jakim typem kloc-
ka zderzyła się piłeczka i podejmuje odpo-
wiednie czynności polegające na odgrywa-
niu odpowiedniego dźwięku, wyświetleniu
efektów specjalnych czy zwiększeniu punk-
tacji gracza. Oczywiście wszystkie funk-
cje aplikacji, czyli PlaySounds , AddScore ,
AddParticles , EndLevel czy Log , mu-
szą być wcześniej zarjestrowane tak, aby
Lua mogła je zawołać (tak jak opisaliśmy
to wcześniej). I tak, kiedy piłeczka ude-
rzy w klocek typu block_death , odgrywa-
my odpowiedni dźwięk, wyświetlamy od-
powiedni efekt w miejscu piłeczki i prze-
kazujemy do kodu aplikacji informację o
niepomyślnym zakończeniu planszy. Na-
tomiast w przypadku trafienia w klocek ty-
pu block_normal losujemy jeden z trzech
dźwięków, odgrywamy go i dodajemy gra-
czowi 10 punktów.
Dzięki takiemu podejściu możemy doda-
wać nowe typy klocków i kontrolować zacho-
wanie podczas kolizji z nimi bez zmiany ko-
du aplikacji.
Listing 10. Obsługa kolizji w prostej grze typu arkanoid
struct ScollInfo {
/// nazwa typu klocka
std :: string Block ;
/// pozycja piłeczki w momencie zderzenia
loat X , Y ;
};
SCollInfo ci ;
if ( IsCollision ( & ci ))
{
/// pobranie funkcji z globalnej tablicy skryptu
lua_getglobal ( s , "OnCollision" );
if ( ! lua_isnil ( s , - 1 ))
{
/// stworzenie nowej tablicy na szczycie stosu
lua_newtable ( s );
/// zarejestrowanie table.block
lua_pushstring ( s , ci . Block . c_str ());
lua_setield ( s , - 2 , "block" );
/// zarejestrowanie table.x
lua_pushnumber ( s , ci . X );
lua_setield ( s , - 2 , "x" );
/// zarejestrowanie table.y
lua_pushnumber ( s , ci . Y );
lua_setield ( s , - 2 , "y" );
/// wywołanie funkcji skryptu
lua_call ( s , 1 , 0 );
}
}
Standardowe biblioteki LUA
Lua posiada bogaty zestaw narzędzi wyższe-
go poziomu zawartych we wbudowanych bi-
bliotekach standardowych. Do tych biblio-
tek należą:
Listing 11. Przykładowa funkcja w Lua obsługująca kolizje
• operacje na łańcuchach znaków – na-
rzędzia umożliwiające zaawansowa-
ne operacje na łańcuchach znaków, tj.
wyszukiwanie, wyodrębnianie i za-
miana podłańcuchów, dopasowywa-
nie do wzorca, formatowanie tekstów
itp.;
• operacje na tablicach – rozszerzenia
umożliwiające bardziej wyrafinowane
operacje na tablicach w Lua (np. sorto-
OnCollision = function ( event )
if event . block == "block_bonus" then
PlaySound ( "bonus.wav" );
AddScore ( 100 );
elseif event . block == "block_death" then
PlaySound ( "death.wav" );
AddParticles ( event . x , event . y , "explosion" );
EndLevel ( false );
elseif event . block == "block_target" then
PlaySound ( "fanfare.wav" );
AddParticles ( event . x , event . y , "fanfare" );
AddScore ( 1000 );
EndLevel ( true );
elseif event . block == "block_normal" then
local snd_table = { "hit_n1.wav" , "hit_n2.wav" , "hit_n3.wav" };
PlaySound ( snd_table [ math.random ( 3 )]);
AddScore ( 10 );
else
PlaySound ( "default.wav" );
end ;
��
��
��
��
��
��
Log ( string.format ( "Collision with \"%s\" at (%f, %f)" , event . block , event . x ,
event . y ));
end ;
Rysunek 1. Parametry funkcji na stosie oraz ich
indeksy w Lua
50
08/2009
441671625.035.png 441671625.036.png 441671625.037.png 441671625.038.png 441671625.039.png 441671625.040.png 441671625.041.png
 
Zgłoś jeśli naruszono regulamin