A Lua programozási nyelv

Fordítók



Faktoriális



-- factorial function function fact(n) if n == 0 then return 1 else return n*fact(n-1) end end n=arg[1] or 10 -- for other values, do lua fib.lua XX n=tonumber(n) if n < 0 then print("Pozitiv szamot kerek!") else print(fact(n)) end

Faktoriális (coroutine)



function generatefact (n) return coroutine.wrap(function () local a, b = 1, 1 while a <= n do coroutine.yield(b) a, b = a+1, b*(a+1) end end) end for i in generatefact(10) do print(i) end

Fibonacci



-- very inefficient fibonacci function function fib(n) if n<2 then return n else return fib(n-1)+fib(n-2) end end n=arg[1] or 24 -- for other values, do lua fib.lua XX n=tonumber(n) print(fib(n))

Fibonacci (coroutine)



function generatefib (n) return coroutine.wrap(function () local a,b = 1, 1 while a <= n do coroutine.yield(a) a, b = b, a+b end end) end for i in generatefib(1000) do print(i) end

QSort



-- two implementations of a sort function -- this is an example only. Lua has now a built-in function "sort" function qsort(x,l,u,f) -- x: table, l:first index, u:last index, f:function if l < u then local m=math.random(u-(l-1))+l-1 -- choose a random pivot in range l..u x[l],x[m]=x[m],x[l] -- swap pivot to first position local t=x[l] -- pivot value m=l local i=l+1 while i<=u do if f(x[i],t) then m=m+1 x[m],x[i]=x[i],x[m] -- swap x[i] and x[m] end i=i+1 end x[l],x[m]=x[m],x[l] -- swap pivot to a valid place -- x[l+1..m-1] < x[m] <= x[m+1..u] qsort(x,l,m-1,f) qsort(x,m+1,u,f) end end function selectionsort(x,n,f) -- move the greater element to the first place, then the second greater to the local i=1 -- second place, and so on... while i<=n do local m,j=i,i+1 while j<=n do if f(x[j],x[m]) then m=j end -- x[j]>x[m] j=j+1 end x[i],x[m]=x[m],x[i] -- swap x[i] and x[m] i=i+1 end end function show(m,x) io.write(m,"\n\t") local i=1 while x[i] do io.write(x[i]) i=i+1 if x[i] then io.write(",") end end io.write("\n") end function testsorts(x) local n=1 while x[n] do n=n+1 end; n=n-1 -- count elements show("original",x) qsort(x,1,n,function (x,y) return x<y end) show("after quicksort",x) selectionsort(x,n,function (x,y) return x>y end) show("after reverse selection sort",x) qsort(x,1,n,function (x,y) return x<y end) show("after quicksort again",x) end -- array to be sorted x={"Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"} testsorts(x)

Memory manager



/* ** $Id: lmem.c,v 1.70 2005/12/26 13:35:47 roberto Exp $ ** Interface to Memory Manager ** See Copyright Notice in lua.h */ #include <stddef.h> #define lmem_c #define LUA_CORE #include "lua.h" #include "ldebug.h" #include "ldo.h" #include "lmem.h" #include "lobject.h" #include "lstate.h" /* ** About the realloc function: ** void * frealloc (void *ud, void *ptr, size_t osize, size_t nsize); ** (`osize' is the old size, `nsize' is the new size) ** ** Lua ensures that (ptr == NULL) iff (osize == 0). ** ** * frealloc(ud, NULL, 0, x) creates a new block of size `x' ** ** * frealloc(ud, p, x, 0) frees the block `p' ** (in this specific case, frealloc must return NULL). ** particularly, frealloc(ud, NULL, 0, 0) does nothing ** (which is equivalent to free(NULL) in ANSI C) ** ** frealloc returns NULL if it cannot create or reallocate the area ** (any reallocation to an equal or smaller size cannot fail!) */ #define MINSIZEARRAY 4 void *luaM_growaux_ (lua_State *L, void *block, int *size, size_t size_elems, int limit, const char *errormsg) { void *newblock; int newsize; if (*size >= limit/2) { /* cannot double it? */ if (*size >= limit) /* cannot grow even a little? */ luaG_runerror(L, errormsg); newsize = limit; /* still have at least one free place */ } else { newsize = (*size)*2; if (newsize < MINSIZEARRAY) newsize = MINSIZEARRAY; /* minimum size */ } newblock = luaM_reallocv(L, block, *size, newsize, size_elems); *size = newsize; /* update only when everything else is OK */ return newblock; } void *luaM_toobig (lua_State *L) { luaG_runerror(L, "memory allocation error: block too big"); return NULL; /* to avoid warnings */ } /* ** generic allocation routine. */ void *luaM_realloc_ (lua_State *L, void *block, size_t osize, size_t nsize) { global_State *g = G(L); lua_assert((osize == 0) == (block == NULL)); block = (*g->frealloc)(g->ud, block, osize, nsize); if (block == NULL && nsize > 0) luaD_throw(L, LUA_ERRMEM); lua_assert((nsize == 0) == (block == NULL)); g->totalbytes = (g->totalbytes - osize) + nsize; return block; }

Rendezés és keresés progress barral

Készítette: Czövek Aurél, 2010.
Fejlesztve és tesztelve a Lua for Windows csomaggal.
Letöltéshez -->

A példaprogram a következő részekből áll:

Mindkét szkript felhasználja az animációs könyvtárat, így mindig látható, éppen hol tart az aktuális művelet.

Forrásfájlok tömörítve: itt.

Bellman-Ford

Az alábbi példaprogram a Bellman-Ford algoritmussal egy legrövidebb utat határoz meg egy irányítatlan gráfban két csúcs között. A bemeneti fájl nevét parancssori argumentumként kell megadni a Lua programnak.

Az input fájlt első sora a forrás és cél csúcs sorszámát tartalmazza. A további sorok az éleket jelölik. Az első két komponens az él két csúcspontjának sorszámát, a harmadik komponens pedig az adott él költségét jelöli.

3 6 1 2 1 1 3 3 2 3 2 3 4 5 2 5 4 4 5 6 4 7 5 5 6 1 6 7 3
edge_list = {} ---------- Gráf felépítése fájlból ---------- file = io.open(arg[1]) start = file:read("*n") target = file:read("*n") while true do from = file:read("*n") to = file:read("*n") cost = file:read("*n") if from == nil then break end if edge_list[from] == nil then edge_list[from] = {} end if edge_list[to] == nil then edge_list[to] = {} end table.insert(edge_list[from], {id = to, cost = cost}) table.insert(edge_list[to] , {id = from, cost = cost}) end file:close() ---------- Bellman-Ford ---------- parent = {} distance = {} distance[start] = 0 for k = 1, #edge_list - 1 do for i = 1, #edge_list do for j = 1, #edge_list[i] do neighbour = edge_list[i][j] if not distance[neighbour.id] or distance[i] and distance[i] + neighbour.cost < distance[neighbour.id] then if distance[i] then distance[neighbour.id] = distance[i] + neighbour.cost parent[neighbour.id] = i end end end end end ---------- Eredmény kiírása ---------- for i = 1, #distance do print("distance[" .. tostring(i) .. "] == " .. tostring(distance[i])) end for i = 1, #parent do print("parent[" .. tostring(i) .. "] == " .. tostring(parent[i])) end current = target while current do print(current) current = parent[current] end

LuaSpline

Készítette: Kustra László Zsolt, 2012.
A program Java környezetbe ágyazott Lua szkriptek futtatását mutatja be egy egyszerű görberajzoló program keretein belül.

Letöltés: futtatható jar, forráskód, bezier.lua, circle.lua, zigzag.lua, interpolator.lua
LuaSpline screenshot

A linkelt forráskód egy Eclipse projektet tartalmaz, a program futtatásához Java SE 1.6 vagy magasabb verzió javasolt.

A program egy görbét rajzol ki, amit ún. kontrollpontok segítségével manipulálhatunk. (Mint ahogy például a Bézier-görbéknél is.) A forráskód legérdekesebb része a hu.elte.inf.luaspline.model.CurveGenerator interfész, ami egy tetszőleges paraméterezett görbét ír le. Ezen interfész két implementációval rendelkezik:

A program többi része – azaz a görbét kirajzoló kód – nem tud arról, hogy az épp kirajzolt görbét generáló kód Javaban vagy Luában íródott-e. Egyetlen osztály implementációjának változtatásával szabadon megváltoztathatjuk a programunk Lua szkriptelési interfészét, vagy akár le is cserélhetjük azt, hogy a program egy másik szkriptnyelvet használjon. Ennek elérése volt a célunk a program létrehozásakor.

Általános nyelvi lehetőségek

Készítette: Németh Nándor, 2013.
A következő programok a nyelv egyes elemeit mutatják be, kitérve az esetlegesen előforduló hibázási lehetőségekre.
Használt futtatókönyezet: Lua for Windows

  • tipusok.lua: Ebben a mintaprogramban bemutatom a nyelv típusait a műveleteikkel. Ez a kód mutatja be a többszörös értékadás lehetőségét is.
  • lathatosag.lua: Itt ismerkedhetünk meg az egyes változók láthatóságával.
  • fuggveny.lua: Ez a mintaprogram mutatja be a függvény definiálások lehetőségeit, a rekurziót és a speciális paraméterezéseket. Itt láthatunk példát metódusok definiálására.
  • ciklus.lua: Ebben a mintaprogramban az 1,2,3,4,5 számok kiíratása során ismerhetjük meg a ciklusok definiálását, illetve a break utasítást.
  • hibakezeles.lua: Ebben a rövid programban láthatunk példát a hibák generálására, illetve, a biztonságos függvényhívásokra.
  • tobbszalusag.lua: A program bemutatja a többszálúság lehetőségeit a nyelvben.
  • Letöltés: forráskódok

    Osztály megvalósítás,dinamikus kötés

    Készítette: Hack János, 2013.
    A program egy egyszerű példa feladaton keresztül mutat be egy osztály implementációt, valamint egy könytárat ami támogatja a dinamikus kötést és virtuális függvényeket.

    A programok egy a geometriai alakzatok megvalósításának osztály hierarchiájára épülő primitív feladatot oldanak meg. A feladat pontos leírását lásd a forráskódok elején. Az egyik megvalósítás egy saját osztály implementációt használ, ami nem támogatja a virtuális függvényeke, a másik egy külső könyvtárat használ, lásd a kódban vagy az Objektum-orientált programozás fejezet Polimorfizmus, Virtuális függvények alfejezetében.

    Lua C API Qt használatával

    Készítette: Bodnár István, 2013.
    A következő program a Lua C API használatát mutatja be Qt környezetben egy egyszerű példán keresztül.
    Fejlesztőkörnyezet: QtCreator

  • script.lua: Néhány egyszerűbb matematikai függvény implementációja lua-ban, megjelenítéshez.
  • function2.lua: Sin, cos, tan, stb. függvények kombinációját tartalmazó lua script.
  • function3.lua: Ez a script egy random nevű függvényt tartalmaz, ami egy adott paraméterhez egy véletlen számot add hozzá és ezt adja eredményül.
  • A program lua scripteket tud betölteni, majd az ezekben található függvényeket meghívva kirajzolja őket a koordinátarendszerben. A függvények a Run... menüpont választásával jeleníthetőek meg. Itt ügyeljünk a helyes név megadására. Az Open script... menüpont választásával tölthetőek be a lua script fájlok. A források közt néhány példa lua script fájl is található a teszteléshez.

    Letöltés: LuaWithQt

    Lua a Metin2 játékban

    Készítette: Horvat Franjo, 2013.
    A következő program a Lua felhasználását mutatja be MMORPG-s játékoknál.

    A Lua-t, mint programozási nyelvet, többek között a Metin2 MMORPG játékban is használják. A MMORPG (Massively Multiplayer Online Role-Playing Game – nagyon sok szereplős online szerepjáték) Interneten, online játszható szerepjáték. A Metin2, mint az MMORPG-s játékok többsége kitalált fantasy témákon alapul, és a játék célja a játékos karakterének fejlesztése. A játéktér PvE és PvP alapú is egyben. PvE (player vs environment) játéktér azt jelenti, hogy a játékos más játékosokkal együtt az adott terület szörnyei ellen harcolhat. PvP (player vs player) játéktér jelentése, hogy a játékosok egymás ellen is harcolhatnak.

    Felépítés:
    A játék felépítésileg áll: -szerverből :A szerver motorja vagy más néven game file-ja C nyelven iródott, ez felelős az üzenet fogadásért, üzenet feldolgozásért valamit üzenet küldésért. -kliensből : A kliens áll egy C nyelven írt kliens motor file-ból és Pythonban írt GUI-ból. -adatbázisból : itt is, mint minden minimális biztonsággal rendelkező rendszernél, csak a szerver módosíthatja az adatokat (a kliens csak szerveren keresztül kommunikál az adatbázissal).

    Működés:
    Szerver inditás során , a szerver betölt a memóriájába egy konzisztens szerver állapotot. Itt jön be a LUA szerepe. LUA-ban van megírva a játékban szereplő összes küldetés, amelyek segítségével a játék sokkalta jobban játszhatóbb, emberbarátibb. Küldetések alatt ne csak azokra gondoljunk amik a karakter fejlődését segítik, hanem gondoljunk olyanokra is amelyek a szerver karbantarthatóságát segítik elő stb.

    LUA a Metin2-ben:
    Mint azt tudjuk a LUA nyílt forráskódú ezálltal személyre vagy rendszerre szabhatjuk annak működését, kivehetünk belőle, módosíthatunk benne és hozzáadhatunk új részeket. Itt is ez történt. A LUA egy változata van jelen ami ki lett egészítve különféle függvényekkel. Ilyenek például az adatbázis mezőinek lekérdezésére szolgáló, és az adatbázis mezőinek megváltoztatására szolgáló függvények.
    Nézzünk néhány példát ezekre:
    pc.gethp() - lekérdezhetjük a felhasználó karakterének életpontjait
    pc.get_local_x() - lekérdezhetjük a felhasználó karakterének x koordinátás pozícióját
    pc.get_local_y() - lekérdezhetjük a felhasználó karakterének y koordinátás pozícióját
    pc.get_account_id() - lekérdezhetjük a felhasználó accountjának azonosítóját
    pc.get_name() - lekérdezhetjük a felhasználó karakterének nevét
    pc.give_exp(int mennyiseg) - adhatunk fejlődéspontokat, amivel a karakter fejleszthető
    pc.give_gold(int mennyiseg) - adhatunk a felhasználónak játék pénzt
    pc.give_item(int id) - tárgyat adhatunk a felhasználó karakterének

    A példaprogram a játék azon részét valósítja meg, amikor a játékos karakterével teleportálni szeretne.

    Letöltés: LuaMetin2

    LuaPaint

    Készítette: Pintér Krisztián, 2014.

    A LuaPaint segítségével Lua szkriptekkel rajzolhatunk BMP ábrákat.
    A Lua szkriptben előszőr az image(szélesség,magasság) függvény segítségével kell inicializálnunk a rajzvásznat, majd a pixel, line és circle függvények segítségével rajzolhatunk.
    Példa:

    local lp = require "luapaint" image(400,400) circle(lp.point(100, 200),50,lp.color(255, 0, 0)) line(lp.point(100, 200), lp.point(200, 300), lp.color(0,0,255)) pixel(lp.point(300,300),lp.color(0,0,0))

    A program felépítése

    A főprogram a main.c fájlban van, ez futtatja a Lua szkriptet. A rajzolást a C-ben írt GUT könyvtár valósítja meg.
    Luában írt adattípusok a rajzoláshoz a luapaint.lua fájlban vannak.
    Egy függvény grafikon rajzoló példaprogram a plot_function.lua fájlban van.
    Egy egyszerű Logo implementáció a luaturtle.lua fájlban van. LuaTurtle példaprogramok a koch.lua, hilbert_curve.lua, dragon_curve.lua és a sierpinski.lua fájlban találhatóak.

    main.c

    #include #include "lua.h" #include "lualib.h" #include "lauxlib.h" #include "GUT.h" // Segédfüggvény egészek Lua táblából való kiolvasására // L - a Lua állapot // keys - a Lua táblából kiolvasandó mezők nevei // vals - tömb, ahova a függvény a kiolvasott egészeket írhatja void load_ints_by_key(lua_State *L, char *keys[], int *vals); // Beágyazott függvények // Kép inicializálása, ez az első függvény amit rajzolás előtt meg kell // hívni a szkriptben int init_image(lua_State *L); // Pixel rajzolása int draw_pixel(lua_State *L; // Vonal rajzolása int draw_line(lua_State *L); // Kör rajzolása int draw_circle(lua_State *L); int main(int argc, char *argv[]) { if(argc < 3) { printf("Usage: luapaint < script > < output bmp >"); } else { lua_State* L = luaL_newstate(); luaL_openlibs(L); // Beágyazandó függvények regisztrálása lua_register(L, "image" , init_image); lua_register(L, "pixel" , draw_pixel); lua_register(L, "line" , draw_line); lua_register(L, "circle", draw_circle); if(luaL_dofile(L, argv[1])) { int i; // Hiba esetén a stack kiíratása for(i = -lua_gettop(L); i < 0 ; ++i) printf("%s\n", lua_tostring(L, i)); } // Lemezre írjuk a képet GUT_output_bmp(argv[2]); GUT_close(); lua_close(L); } return 0; }

    GUT.h

    #ifndef _GUT_H_ #define _GUT_H_ #include #include #include // Vászon inicializálása void GUT_init(int w, int h); // Inicializáltság lekérdezése int GUT_is_init(); // Vászon felszabadítása void GUT_close(); // BMP mentése void GUT_output_bmp(char * fname); // Rajzolószín beállítása void GUT_set_color( int r, int g, int b ); // Pixel rajzolása void GUT_draw_pixel( int x, int y ); // Vonal rajzolása void GUT_draw_line( int x0, int y0, int x1, int y1); // Kör rajzolása void GUT_draw_circle( int x, int y, int rad );

    luapaint.lua

    local function color(r,g,b) return { r = r, g = g, b = b } end -- 2D pont/vektor típus local function point(x,y) return setmetatable( { x = x, y = y, -- Vektor elforgatása origó körül rotate = function(self, angle) local rads = angle * math.pi / 180 return point(self.x * math.cos(rads) - self.y * math.sin(rads), self.x * math.sin(rads) + self.y * math.cos(rads)) end, -- Vektor normalizálása normalized = function(self) local len = self:length() return point(self.x / len, self.y / len) end, -- Vektor hossza length = function(self) return math.sqrt(self.x * self.x + self.y * self.y) end }, { -- Vektorösszeg __add = function(lhs, rhs) return point(lhs.x + rhs.x, lhs.y + rhs.y) end, -- Szorzás skalárral jobbról __mul = function(lhs, rhs) return point(lhs.x * rhs, lhs.y * rhs) end }) end return { color = color, point = point }

    plot_function.lua

    local lp = require "luapaint" -- Intervallum típus function range(low, high) local l local h if low < high then l,h = low,high else l,h = high,low end return { low = l, high = h } end -- Függvényrajzoló függvény -- paraméterek: -- fun - R->R függvény, kirajzolandó függvény -- dest - point, a kirajzolt grafikon bal felső sarka -- size - point, a kirajzolt grafikon mérete -- dom - range, a megjelenítendő értéktartomány -- rng - range, a megjelenítendő értékkészlet -- draw_axes - bool, kirajzoljuk-e az x és y tengelyeket function plot_function(fun, dest, size, dom, rng, draw_axes) local d1 = dest -- bal felső sarok local d2 = dest + size -- jobb alsó sarok -- keret kirajzolása line(d1,lp.point(d1.x,d2.y),lp.color(0,0,0)) line(d1,lp.point(d2.x,d1.y),lp.color(0,0,0)) line(d2,lp.point(d1.x,d2.y),lp.color(0,0,0)) line(d2,lp.point(d2.x,d1.y),lp.color(0,0,0)) -- tengelyek kirajzolása, draw_axes alapértelmezésben true if draw_axes == nil or draw_axes == true then local axis_x = (-rng.low)/(rng.high-rng.low) local axis_y = (-dom.low)/(dom.high-dom.low) if 0 < axis_x and axis_x < 1 then line( lp.point(0 , axis_x * size.y) + dest , lp.point(size.x, axis_x * size.y) + dest , lp.color(0,0,0)) end if 0 < axis_y and axis_y < 1 then line( lp.point(axis_y * size.x, 0 ) + dest , lp.point(axis_y * size.x, size.y) + dest , lp.color(0,0,0)) end end local height = size.y local width = size.x -- függvény kirajzolása, minden pixeloszlopbani kiértékelésével for i=0,width-1 do local ii0 = ( i /(width-1))*(dom.high-dom.low)+dom.low local ii1 = ((i+1)/(width-1))*(dom.high-dom.low)+dom.low local j0 = 1-(fun(ii0)-rng.low)/(rng.high-rng.low) local j1 = 1-(fun(ii1)-rng.low)/(rng.high-rng.low) if j0 < 0 then j0 = 0 elseif j0 > 1 then j0 = 1 end if j1 < 0 then j1 = 0 elseif j1 > 1 then j1 = 1 end line( lp.point(i ,j0*height) + dest , lp.point(i+1,j1*height) + dest , lp.color(0,0,0)) end end

    luaturtle.lua

    local lp = require "luapaint" -- A teknőc állapotát leíró változók. local pos = lp.point(0,0) -- hely local dir = -90 -- szög local pendn = true -- toll letéve local penclr = lp.color(0,0,0) -- toll színe -- Egyszerű setterek local function pencolor(color) penclr = color end local function penup() pendn = false end local function pendown() pendn = true end -- Forgatás local function left(angle) dir = (dir - angle) % 360 end local function right(angle) dir = (dir + angle) % 360 end -- Teknőc áthelyezése rajzolás nélkül local function moveto(target) pos = target end -- Rajzolás előre local function forward(distance) local rads = dir * math.pi / 180 -- Az új koordinátákat átszámoljuk a teknőc polárkoordinátarendszeréből local newpos = pos + lp.point(math.cos(rads), math.sin(rads)) * distance if pendn then line(pos, newpos, penclr) end pos = newpos end local function backward(distance) forward(-distance) end return { pencolor = pencolor, penup = penup, pendown = pendown, left = left, right = right, moveto = moveto, forward = forward, backward = backward }

    koch.lua

    local lp = require "luapaint" local lt = require "luaturtle" function koch(step, length) if step == 0 then lt.forward(length) else koch(step - 1, length/3) lt.left(60) koch(step - 1, length/3) lt.right(120) koch(step - 1, length/3) lt.left(60) koch(step - 1, length/3) end end image(800,250) lt.moveto(lp.point(0,240)) lt.right(90) koch(5, 800)

    Letöltés: LuaPaint

    proteaAudio - cross-platform 2D audio library for C++ and Lua

    Példaprogramot készítette: Tomcsik Bence Tibor, 2014.

    A proteaAudio open-source library-vel egyaránt használhatjuk az RtAudio, alacsony szintű audio input/output API-t vagy a több platformon is használatos SDL multimédia library-t.
    A példaprogram bemutatja a legegyszerűbb függvényeket amik segítségével egyszerű dalok lejátszására alkalmas programokat írhatunk.

    Figyelem: Halkítsd le a hangerőt a program futtatásakor!!!!

    proteaAudio hivatalos oldala

    Letöltés: LuaSound

    Alapértelmezetten a proteaAudio belső része az RtAudio alacsony szintű valós idejű ki-/bemeneti audio API-t használja, így ezt és néhány belső rendszerszintű lib-et leszámítva nincs más függősége.
    További lehetőségként tartalmaz opcionális binding-okat a több platformra is portolható SDL multimédia könyvtárhoz.
    Számos profi szolgáltatást nyújt amelyek segítségével akár egy komplett stúdió programot is össze tudnánk állítani. Kezeli továbbá a .wav, .mp3, stb. kiterjesztésű audio fájlokat.

    A proteaAudio tartalmaz egy majdnem teljes Lua binding listát, amelyek megfelelnek a C++ API-knak. Alapértelmezetten ezek a Lua binding-ok egy dll-ként vannak fordítva, amely az RtAudio backend-nek felel meg és a következő paranccsal importálható:

    require("proAudioRt")

    A példaprogramban található pár függvény amelyek működéséről és paramétereiről a hivatalos oldalon és a program kommentjei között is olvashatsz.

    Felmerülhet a kérdés, hogy ha szeretnénk egy kotta hangjait leprogramozni hogyan lássunk hozzá?
    Ehhez először röviden leírnám, hogy mi is a használandó folyamat amit követtem a példaprogramban:

    Azt, hogy a kotta hangjainak mely számok felelnek meg, az csak az implementációnktól függ:
    A playNote(sample, pitch, duration) függvény amit én használok a programomban azt jelenti, hogy az adott hang amit létrehoztam azt a pitch paraméter szerint tolom el az alaphangtól és duration paraméter segítségével mondom meg, hogy meddig tartom ki.

    Ezt a pitch paramétert úgy használom fel, hogy elosztom 12-vel, mert ennyi félhang van egy oktávon belül. Ez lesz a kitevője a 2 alapú hatványomnak. Ez azért jó, mert így nem csak 1 oktávon belül tudok mozogni. A megkapott érték mondja meg, hogy mennyivel toljuk el az alaphangot. Ha 0-át adunk meg akkor az érték 1 lesz és ez az alaphangnak felel meg. Ha 12-őt, akkor az érték 2 lesz ami 1 oktávval magasabban lévő hangot adja meg.

    Innentől kezdve egy dolgunk van hátra:
    Mi az általunk létrehozott hang alaphangja?
    A példaprogram esetében 440 Hz frekvenciájú hangot hoztam létre. Ennek A az alaphangja ami 0-nak felel meg. A' (egy oktávval magasabban lévő alaphang) 12-nek felel meg.

    Egy kicsi zeneelmélet:
    Egy oktávban 8 hang:
    A-H-C-D-E-F-G-A'

    és 13 (13. az alaphang) félhang van:
    A-Aisz-H-C-Cisz-D-Disz-E-F-Fisz-G-Gisz-A'

    Azért nem 17, mert van két hangpár amik között a távolság csak félhang. Ezek a H-C és az E-F.
    Most, hogy tudjuk a hangokat és azt, hogy a függvényünkben a szám félhangonkénti eltolást jelent, könnyen ki tudjuk számolni, hogy milyen paramétereket kell használnunk a megfelelő hangokhoz. Feltéve, hogy tudunk kottát olvasni. A példaprogramban 2 hanggal fentebb eltoltam minden hangot, így az én alaphangomnak nem 0 az értéke, hanem 4. Ezt csak a hangzás miatt csináltam.

    Egyszerre akár több hangot is lejátszhatunk, így a többszólamúság sem akadály.

    Lua jellegzetességek unit tesztekbe ágyazva

    Példaprogramot készítette: Kovács Krisztina Magdolna, 2014.

    A program futtatásához Luaunit szükséges.
    A példaprogram a Lua olyan jellegzetességeit mutatja be, amelyek a más nyelvek felől érkező programozók számára megtévesztőek, szokatlanok lehetnek. Mindez unit tesztek formájában került implementálásra, így a program futtatása egyúttal bizonysággal is szolgál a hozott példák helyességére, helyes működésére.

    Luaunithivatalos oldala

    Letöltés: Luaunit Tutorial

    Lua Threading bemutatása

    Példaprogramot készítette: LepártLevente Béla, 2014.

    A csomag 2 példaprogramot tartalmaz. Az első az unschedulled coroutineok használatát szemlélteti, mígy a másik egy schedulled exec szerű viselkedést mutat be.

    Bővebb leírás az alábbi lapokon található:

    Letöltés: Lua Threading Totorial

    Lua Tcp/Ip bemutatása

    Példaprogramot készítette: LepártLevente Béla, 2014.

    A csomag 2 példaprogramot tartalmaz. Az első az egy egszerű szerver/kliens kommunikációt mutat be, a második azonban egy bonyolultabb messanger-t valósít meg.

    Bővebb leírás az alábbi lapon található: luasocket reference

    Letöltés: Lua Tcp/Ip Tutorial

    egy Lua WoW addon bemutatása

    A World of Warcraft egy igen népszerű MMO-RPG, és a játékhoz készült addonok is különösen közkedveltek, mivel javítják a játékélményt és könnyítik a játszhatóságot. Ebben a fejezetben egy World of Warcraft addont készítünk melyhez alapvető Lua ismeretek szükségesek.

    Aki már használt WoW addont, az valószínűleg tisztában van azzal, hogy az addon telepítéshez elegendő annak mappáját bemásolni az /Interface/AddOns könyvtárba, ami a játék könyvtárában található (alapértelmezetten a C:/Program Files (x86)/World of Warcraft elérési úton). Ha az addon stimmel (nem tartalmaz hibákat, megfelel a verziója... stb.), akkor ezzel installáltuk, a játék (újra)indítása után használhatjuk is. Ha megvizsgáljuk az egyes addonokhoz tartozó mappák tartalmát, azt láthatjuk, hogy minden addon (még a Blizzard által szállított gyári addonok is), követ bizonyos szabályokat. Ezek közül is a két legfontosabb, melyet mi is követni fogunk, a következő:

    Minden addonnak van egy saját könyvtára, az /Interface/AddOns mappában. Minden ilyen könyvtárban kell lennie egy .toc file-nak melynek neve meg kell, hogy egyezzen az adott addon könyvtár nevével, és az addonnal kapcsolatos információkat tartalmazza. Elsőként tehát, készítsünk egy egyszerű Hello World addont, mely egy üdvözlő üzenetet ír ki a képernyőre. Először is, hozzunk létre egy "HelloWorld" nevű könyvtárat az /Interface/AddOns mappában, illetve ebben egy "HelloWorld.toc" (Table Of Contents) file-t.

    Az indítása során a játék ezeket a TOC file-okat nyitja meg elsőként, így különösen fontos, hogy mind formailag mind pedig tartalmilag megfelelőek legyenek. A file elejére direktívákat lehet (és kell is) írni, mely olyan információkat tartalmaz, mint például, hogy az addon melyik játék verzióhoz készült, az addon neve, az addon verziója, az addon alkotója, megjegyzések, ...stb. Ezeket két hashmark prefix-szel jelölve sorolhatjuk fel, melyet egy space, az általunk definiálni kívánt property neve, majd egy kettőspont követ, végül pedig az az érték, amivel a property-t szeretnénk feltölteni. A verzióhoz tartozó property-t leszámítva, mely a ##Interface: XXXX direktívát követi, az átlag property nevek igen beszédesek, akár még ki is találhatóak. Esetünkben, a HelloWorld.toc file tartalma tehát az alábbihoz hasonlóan kell, hogy kinézzen:

    ## Interface: 50001 ## Title: Hello World ## Author: John Smith ## Version: 0.1

    Megj.: Bővebben a property tag-ekről itt:

    TOC format

    A játék bármely nem '##' kezdetű sort file-névként kezel, melyet megpróbál az addon betöltése során futtatni/betölteni (például egy karakterrel történő belogolás során). Ezen file-ok betöltése a toc-file-ban történt felsorolásukkal megegyező sorrendben hajtódik végre. Jelen esetben, csak egy egyszerű "Hello World"-öt szeretnénk kiíratni egy Lua script segítségével, így hozzunk is létre mondjuk egy 'main.lua' nevű file-t, mely az addonunkhoz tartozó programkódot tartalmazza majd, illetve soroljuk fel a file-unk nevét a 'HelloWorld.toc' file végén, hogy indításkor az betöltésre kerüljön.

    main.lua

    Mivel ezzel az addonunk betöltéséhez szükséges TOC file elkészült, egy dolgunk maradt hátra, megírni a Lua scriptet mely megvalósítja az általunk kívánt funkcionalitást. Az addon-készítők számára a World of Warcraft interface-ének köszönhetően szamos custom függvény és table erheto el, hogy ezzel elősegítsék a játék customizálását. Jelen esetben, persze csak egy text outputra van szükségünk, melyet kétféleképpen is elerhetunk: a print függvény hívásával az üzenetünk a chat ablakban jelenik meg, míg a message függvény hívásával egy pop-up ablakban. Itt jegyeznénk meg, hogy a message függvényt a Blizzard deprecated-nek nyilvánította, így rövidesen már nem lesz elérhető. Így tehát használjuk inkább a print metódust. Adjuk hozzá az alábbi sort a 'main.lua' file-lunkhoz:

    message('Hello World!')

    Ezután indítsuk el a játékot. A karakterválasztás előtt ellenőrizzük, hogy az "Addons" menüpont alatt megjelent-e az addonunk (amennyiben nem, úgy ellenőrizzük a TOC file-lunk tartalmát), majd válasszuk ki karakterünket és logoljunk be. Azt láthatjuk, hogy a chat ablakban megjelent a 'Hello World!' üzenet. Tehát a "Hello World" addonunk működik.

    Ez az addon azonban jelenleg nem túl hasznos, hiszen egy konstans textet ír ki minden egyes belogoláskor. Azonban igen könnyen tudjuk hasznossá tenni. Sok WoW játékos számára a guild (klán) egy olyan nem opcionális szociális konvenció, amire azért van szüksége, mert bónuszokat kap érte. Ha egy játékos tagja egy guildnek, akkor több XP-t kap, vásárolhat egyes vendoroknál, ahol egyébként nem tehetné. Viszont a guildben rossz szemmel nézik, ha az ember logint követően nem köszön... Ha a fenti script-tünket az alábbiakkal módosítjuk:

    SendChatMessage("Hi all!", "GUILD");

    Akkor egy gonddal kevesebb. Egyes szemfüles guildtársaknak persze feltűnhet, hogy mindig ugyanúgy köszönünk. Erre megoldást nyújthat például az alábbi kód:

    local greetings = {} table.insert (greetings, 'Hello!') table.insert (greetings, 'Hi guys!') table.insert (greetings, 'Greetings!') SendChatMessage( (greetings [math.random(1,#greetings)], "GUILD");

    Megj.: sajnos a botolás elkerülése céljából egyes Lua funkciók le vannak tiltva így pl. az 'os' module nem elérhető. Ezért hívjuk az os.time() helyett a globál táblában definiált time() függvényt, illetve mivel sajnos a randomseed állítása is le van tiltva, ezt kerüljük meg a ciklussal.

    A WoW API azonban ennél jóval kreatívabb addonok készítését is támogatja. Lehetőség van például egyes eventekre való regisztrálásra. Mint amikor a karakterünk egy vendorhoz ér, megtehetjük, hogy az értéktelen low-level itemeket automatikusan eladjuk. Ehhez először is be kell regisztrálni arra az eventre, ami akkor váltódik ki, ha egy vendor ablak nyílik.

    Legyen az új addonunk neve JunkSeller, a Lua file neve 'JunkSeller.lua' , a TOC file ugyanígy JunkSeller.toc, illetve legyen egy JunkSeller.xml file-unk is, de erről majd idejében.

    A TOC file tartalma legyen a következő:

    ## Interface: 50400 ## Title: JunkSeller ## Notes: Automaticaly sells all gray items and a list of other items when a merchant window openes ## Author: John Smith JunkSeller.lua JunkSeller.xml

    Az event regisztrációnkat tegyük bele egy egy Init függvénybe. Hogy elkerüljük a lehetséges névütközéseket, init helyett nevezzük a függvényünket junkSellerInit-nek

    function junkSellerInit() junkSellerFrame:RegisterEvent("MERCHANT_SHOW"); end

    Az addonunk a későbbiekben minden itemet elad majd, amely nem túl ritka, viszont tegyük fel, hogy vannak olyan ritkább itemek is, melyek a fenti kategóriába nem esnek bele, ám mi meg szeretnénk tőlük válni

    Megj.: ez általában akkor fordul elő ha egy játékos egy specifikus item kedvéért tisztít ki egy magánál jóval kisebb szintű dungeont újra és újra, amíg az item nem esik. Ekkor általában a többi itemre nincs szüksége, ezért eladja őket.

    Ezután soroljuk fel azokat az itemeket amiktől minden esetben meg szeretnénk válni, ám nem low level-ek.

    Tehát a lista legyen mondjuk a következő:

    junkSellerList = {} junkSellerList ['White Turnip'] = 1 junkSellerList ['Fizzy Faire Drink'] = 1 junkSellerList ['Pickled Kodo Foot'] = 1 junkSellerList ['Spinefish'] = 1

    Az event handler függvényünknek a következő feladatai vannak: Végig kell iterálnia a táskákon, majd azok slotjain. Meg kell néznie, hogy az adott slotban van-e item és ha igen, akkor adott rarity szint alatt van-e. Ha igen, el kell adnia, ha nem akkor meg kell néznie, hogy rajta van-e az általunk explicit haszontalannak ítélt tárgyak listáján. Ha igen, akkor azt is el kell adnia.

    function junkSellerEvent() local junkSellerBag, junkSellerNSlots, junkSellerSlot, junkSellerLink local junkSellerItemName, junkSellerItemLink, junkSellerItemRarity local junkSellerItemLevel, junkSellerItemMinLevel, junkSellerItemType local junkSellerItemSubType, junkSellerItemStackCount local junkSellerItemEquipLoc, junkSellerItemTexture, junkSellerItemSellPrice for junkSellerBag = 0, 4, 1 do junkSellerNSlots = GetContainerNumSlots(junkSellerBag); if junkSellerNSlots ~= nil then for junkSellerSlot = 1, junkSellerNSlots, 1 do junkSellerLink = GetContainerItemLink(bag,junkSellerSlot); if junkSellerLink ~= nil then junkSellerItemName, junkSellerItemLink, junkSellerItemRarity, junkSellerItemLevel, junkSellerItemMinLevel, junkSellerItemType, junkSellerItemSubType, junkSellerItemStackCount, junkSellerItemEquipLoc, junkSellerItemTexture junkSellerItemSellPrice = GetItemInfo(junkSellerLink) -- if this is a very common item the we sell it if junkSellerItemRarity == 0 then print (junkSellerItemLink); UseContainerItem(junkSellerBag,junkSellerSlot); -- else if this is an item that we have declared that we -- does not need elseif junkSellerItemName ~= nil and junkSellerList [caItemName] ~= nil then print (junkSellerItemLink); UseContainerItem(junkSellerBag,junkSellerSlot); end end end end end end

    Megj.: a

    junkSellerItemName, junkSellerItemLink, junkSellerItemRarity, junkSellerItemLevel, junkSellerItemMinLevel, junkSellerItemType, junkSellerItemSubType, junkSellerItemStackCount, junkSellerItemEquipLoc, junkSellerItemTexture junkSellerItemSellPrice = GetItemInfo(junkSellerLink)

    helyett használhattuk volna a

    junkSellerItemName, junkSellerItemLink, junkSellerItemRarity, _, _, _, _, _, _, _, _ = GetItemInfo(junkSellerLink)

    is, vagy el hagyhattuk volna az alulvonásokat, hiszen (még) nem használtuk fel csak az első 3 információt.

    Kezdjük az xml file-lal. A WoW lehetőséget nyújt arra hogy az event regisztrációkat xml segítségével tegyük meg, továbbá xml-ben mondjuk meg a játék számára azt is, hogy az addon betöltésekor mely függvény hívódik meg elsőként.

    JunkSeller.xml

    <Ui xmlns="http://www.blizzard.com/wow/ui/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.blizzard.com/wow/ui/ ..\..\FrameXML\UI.xsd"> <Script file="JunkSeller.lua"/> <Frame name="junkSellerFrame"> <Scripts> <OnEvent> junkSellerEvent(); </OnEvent> <OnLoad> junkSellerInit(); </OnLoad> </Scripts> </Frame> </Ui>

    Ezzel valójában egy csapásra megválaszoltuk mind a három kérdést, hiszen:

    junkSellerFrame egy xml-ben deklarált frame. az xml-ben az tag mondja meg pontosan, hogy mit kell hívni az addon indításakor valamint az tag regisztrálja a függvényünket mint event handlert.

    Irodalom jegyzék:

    Feldolgozásra váró további témák:

    Letöltés: Lua Wow Addon Totorial

    Egyszerű szövegszerkesztő alkalmazás

    Készítette: Fülöp László

    Egy egyszerű szövegszerkesztő alkalmazás Windows Forms GUI felülettel, ami LuaInterface és CLRPackage könyvtárak segítségével lett Lua alatt megvalósítva.

    Forrás: Megjelenítés, Logika