V pátém článku věnovaném programovacím jazykům a taktéž knihovnám, které mohou být vhodné pro výuku programování i základů počítačové grafiky, si ukážeme, jakým způsobem je možné v knihovně LÖVE vytvářet zajímavé grafické efekty s využitím takzvaných částicových systémů.

Obsah

1. Programovací jazyky a knihovny určené pro výuku základů počítačové grafiky (5)

2. Demonstrační příklad číslo 12: změna souřadnicového systému

3. Částicové systémy v knihovně LÖVE

4. Vytvoření a vykreslení jednoduchého částicového systému

5. Parametry částicového systému

6. Demonstrační příklad číslo 13: jednoduchý částicový systém

7. Změna základních parametrů částicového systému: gravitace, změna velikosti částic

8. Demonstrační příklad číslo 14: padající globusy

9. Změna vlastností emitoru částic: počáteční směr a rozptyl

10. Demonstrační příklad číslo 15: ohnivý déšť

11. Změna barvy a rotace emitovaných částic

12. Demonstrační příklad číslo 16: výbuch

13. Repositář se zdrojovými kódy dnešních demonstračních příkladů

14. Odkazy na Internetu

15. Literatura, v níž jsou zmíněny částicové systémy

1. Programovací jazyky a knihovny určené pro výuku základů počítačové grafiky (5)

V předchozích dvou částech [1] [2] seriálu o programovacích jazycích a taktéž o knihovnách, které mohou být použity pro výuku programování i základů počítačové grafiky, jsme se seznámili se základem tvorby aplikací s využitím programovacího jazyka Lua a knihovny LÖVE. I v dnešní části se budeme věnovat popisu možností nabízených touto knihovnou. Nejprve si řekneme základní informace o práci se souřadnicovým systémem (i když je nutné poznamenat, že v případě 2D grafiky se nejedná o tak důležité téma, jako by tomu bylo u „plnohodnotné“ prostorové grafiky) a druhá část článku bude věnována zmínce o takzvaných částicových systémech (particle systems), které jsou v knihovně LÖVE taktéž k dispozici a s jejichž využitím je možné relativně snadným způsobem vytvářet různé grafické efekty a zejména pak animace.

06

Obrázek 1: Screenshot z demonstračního příkladu (změna režimu směšování barev), který jsme si popsali minule.

2. Demonstrační příklad číslo 12: změna souřadnicového systému

Minule jsme se mj. zabývali i problematikou vykreslování a otáčení spritů (rastrových obrázků s průhlednými a poloprůhlednými pixely). Připomeňme si, že pro otáčení spritů je možné ve funkci love.graphics.draw předat i úhel otočení, ovšem vlastní otáčení je implicitně prováděno okolo bodu [0,0], tj. střed otáčení leží v levém horním rohu spritu. Většinou však vyžadujeme, aby se sprite otáčel okolo svého středu a nikoli okolo rohu. Problém s rotací obrázků je možné řešit minimálně dvěma způsoby: změnou souřadného systému, popř. použitím dalších parametrů již zmíněné funkce love.graphics.draw. Toto řešení již známe, takže nám zbývá si vysvětlit, jak je možné změnit souřadný systém (a taktéž jak nastavení vrátit do výchozí podoby, což je neméně důležité). Výchozí nastavení souřadného systému je snadno pochopitelné: jeho počátek leží v levém horním rohu okna, x-ová souřadnice roste v horizontálním směru (doprava), y-ová souřadnice ve směru vertikálním (dolů). Měřítko je nastaveno tak, že jednotka odpovídá jednomu pixelu.

Souřadný systém je interně reprezentován transformační maticí, pro jejíž změnu se používají tyto funkce:

# Funkce Význam
1 love.graphics.push uložení aktuální matice na zásobník (aby se dalo obnovit předchozí nastavení)
2 love.graphics.pop obnovení předchozího nastavení ze zásobníku
3 love.graphics.rotate rotace o zadaný úhel (v radiánech)
4 love.graphics.scale změna měřítka (lze nastavit nezávisle v obou směrech)
5 love.graphics.translate posun

Manipulace se souřadným systémem je v demonstračním příkladu realizována ve funkci drawSprite, jejíž nová podoba vypadá následovně:

--
-- Vykreslení spritu s jeho otočením.
--
function drawSprite(sprite)
    -- uložení transformační matice
    love.graphics.push()
    -- zajištění posunu a rotace
    love.graphics.translate(sprite.x, sprite.y)
    love.graphics.translate(sprite.image:getWidth()/2, sprite.image:getHeight()/2)
    love.graphics.rotate(sprite.r)
    love.graphics.translate(-sprite.image:getWidth()/2, -sprite.image:getHeight()/2)
    -- vykreslení spritu
    love.graphics.draw(sprite.image, 0, 0)
    -- obnovení původní transformační matice
    love.graphics.pop()
end

V této funkci došlo k několika dílčím transformacím, které se postupně skládají (a to jakoby odzadu, protože nemanipulujeme se spritem, ale s plochou, na kterou se vykresluje):

  • Na začátku leží levý horní roh spritu na souřadnicích [0,0]
  • Posun počátku na střed otáčení (nyní je střed spritu na souřadnicích [0,0])
  • Otočení (okolo počátku, tedy okolo středu spritu)
  • Posun zpět
  • Posun celého systému tak, aby se sprite vykreslil na pozici [sprite.x, sprite.y]

02

Obrázek 2: Scéna vykreslená demonstračním příkladem.

03

Obrázek 3: Otočení spritů po uplynutí určitého časového úseku.

Úplný zdrojový kód tohoto demonstračního příkladu vypadá následovně:

--
-- Knihovna LÖVE
--
-- Dvanáctý demonstrační příklad
--
-- Práce se sprity: zobrazení, otočení změnou souřadnicového systému.
--
 
 
 
-- rozměry okna
width = 450
height = 450
 
 
 
-- objekty představující sprity zobrazené v okně
local sprite1 = {x=100, y=100, r=0, dr=-0.17}
local sprite2 = {x=185, y=80,  r=0, dr=0.1}
local sprite3 = {x=300, y=100, r=0, dr=0.05}
 
 
 
--
-- Funkce volaná při inicializaci aplikace.
--
function love.load()
    -- načtení standardního fontu a nastavení grafického režimu
    local font = love.graphics.newFont(love.default_font, 40)
    -- načtení spritů
    sprite1.image = love.graphics.newImage("sprite2.png")
    sprite2.image = love.graphics.newImage("sprite1.png")
    sprite3.image = love.graphics.newImage("sprite2.png")
    love.graphics.setMode(width, height, false, false, 0)
    -- nastavení fontu
    love.graphics.setFont(font)
end
 
 
 
--
-- Vykreslení spritu s jeho otočením.
--
function drawSprite(sprite)
    -- uložení transformační matice
    love.graphics.push()
    -- zajištění posunu a rotace
    love.graphics.translate(sprite.x, sprite.y)
    love.graphics.translate(sprite.image:getWidth()/2, sprite.image:getHeight()/2)
    love.graphics.rotate(sprite.r)
    love.graphics.translate(-sprite.image:getWidth()/2, -sprite.image:getHeight()/2)
    -- vykreslení spritu
    love.graphics.draw(sprite.image, 0, 0)
    -- obnovení původní transformační matice
    love.graphics.pop()
end
 
 
 
--
-- Tato funkce je volána automaticky při překreslení obsahu
-- okna či obrazovky.
--
function love.draw()
    -- vykreslení prvního spritu přes ostatní sprity
    drawSprite(sprite1)
    -- vykreslení druhého spritu přes ostatní sprity
    drawSprite(sprite2)
    -- vykreslení třetího spritu přes ostatní sprity
    drawSprite(sprite3)
 
    love.graphics.print("Press escape to exit.", 30, 433)
end
 
 
 
--
-- Změna rotace spritů v okně
--
function updateSpriteAngle(sprite)
    sprite.r = sprite.r + sprite.dr
end
 
 
 
--
-- Funkce volaná cca 30x za sekundu
--
function love.update(dt)
    updateSpriteAngle(sprite1)
    updateSpriteAngle(sprite2)
    updateSpriteAngle(sprite3)
    local delay = 1/30
    if dt < delay then
        love.timer.sleep(delay - dt)
    end
end
 
 
 
--
-- Callback funkce zavolaná při stisku klávesy.
--
function love.keypressed(k)
    if k == 'escape' then
        love.event.quit()
    end
end
 
 
 
--
-- finito
--

3. Částicové systémy v knihovně LÖVE

V knihovně LÖVE nalezneme podporu i pro takzvané částicové systémy (někdy taktéž nazývané systémy částic, anglicky particle systems). Ty pro relativně velké množství aplikací představují velice silnou modelovací a současně i animační techniku určenou pro vytváření takových objektů, které není možné jednoduše reprezentovat svým povrchem nebo objemem. Jedná se například o objekty představující přírodní fenomény jakými jsou sníh, déšť, oheň, mlha, dým nebo tekoucí voda. Velikou předností částicových systémů je fakt, že se s jejich využitím dají jednoduše vytvářet animace. Při použití klasických modelovacích metod se při animování musí použít složitější techniky, například animační křivky, morfing, přímá kinematika nebo inverzní kinematika, což klade zvýšené požadavky jak na vlastní animační systém, tak i na znalosti a schopnosti uživatele obsluhujícího tento systém (i to je však v knihovně LÖVE alespoň částečně podporováno).

04

Obrázek 4: Výbuch vytvořený pomocí částicových systémů. Rendering tohoto obrázku byl proveden v programu POVRay.

U částicových systémů se při animaci nemusí pracně zadávat jednotlivé polohy částic v čase, ale je možné jednoduše zadat počáteční polohu a rychlost částic (vlastnosti takzvaného emitoru) a poté nechat proběhnout simulaci, ve které se automaticky, podle zadaných fyzikálních vlastností, vypočítají nové polohy částic. Právě z tohoto důvodu jsou částicové systémy oblíbené například mezi tvůrci her. Celý částicový systém je modelován jako soubor určitých základních prvků –částic (particle)– jejichž vlastnosti se průběžně mění v čase. Mezi základní vlastnosti částice patří zejména:

  • Poloha částice v rovině či prostoru (v případě knihovny LÖVE v rovině)
  • Vektor rychlosti částice (počítá se automaticky)
  • Zrychlení částice
  • Hmotnost částice

K těmto základním vlastnostem většinou přidáváme i vizuální vlastnosti, například:

  • Velikost částice a změna velikosti v čase
  • Tvar a způsob vykreslení částice (v knihovně LÖVE se jedná o sprite)
  • Barva částice
  • Obrázek představující částici
  • Průhlednost částice a změna průhlednosti v čase

05

Obrázek 5: Částicové systémy lze použít i při simulaci tekoucí vody. Rendering tohoto obrázku byl opět proveden v programu POVRay. Výpočet tekoucí vody sice není přesný (voda je reprezentována množstvím jednodušších těles), nicméně po účely počítačové grafiky je přesnost dostačující.

Z důvodu vytváření a provádění animací se zavádí také vlastnost nazvaná „doba života částice“. Při simulacích se po uplynutí doby života částice může částice zrušit nebo se na místě zániku částice mohou generovat další částice (rozpad částice). U složitějších částicových systémů lze reagovat i na vzájemné střety částic nebo interakci částic se svým okolím, tj. s tělesy, které se ve scéně nachází (tyto vlastnosti jsou v systému LÖVE podporovány jen v omezeném rozsahu, zabývat se jimi budeme až příště).

06

Obrázek 6: Poměrně jednoduchý dvoudimenzionální částicový systém, kde je každá částice reprezentována jediným pixelem.

4. Vytvoření a vykreslení jednoduchého částicového systému

V knihovně LÖVE jsou částicové systémy (v jednom okamžiku jich totiž může existovat větší množství) představovány objektem nazvaným ParticleSystem. Částicový systém lze vytvořit pomocí funkce (konstruktoru) love.graphics.newParticleSystem(image, buffer), která má dva parametry – obrázek, pomocí něhož se vykreslují jednotlivé částice (typicky načtený z externího souboru) a numerickou hodnotu, kterou je možné omezit maximální celkový počet částic v částicovém systému. V závislosti na konfiguraci se totiž může počet částic v různých časových okamžicích lišit; na začátku „života“ systému typicky ještě neexistují žádné částice.

07

Obrázek 7: Velmi jednoduchý částicový systém vykreslený pomocí systému LÖVE. Vizuální podoba částic je uložena v rastrovém obrázku, na rozdíl od systému zobrazeného na obrázku číslo 7.

Po vytvoření částicového systému a nastavení jeho parametrů (viz též následující kapitolu) lze částicový systém vykreslit do libovolného místa obrazovky (okna) pomocí přetížené funkce love.graphics.draw(particlesystem, x, y), které se předává jak objekt představující částicový systém, tak i souřadnice na obrazovce, ve kterých se má nacházet střed částicového systému. Ovšem již z předchozího dílu víme, že tato funkce má i další volitelné parametry, například otáčení či změnu velikosti. Systém LÖVE neobsahuje žádné další funkce, které by pracovaly s objektem částicového systému, veškeré nastavení jeho parametrů se provádí přímo voláním jeho metod, které jsou popsány v navazující kapitole.

08

Obrázek 8: Další částicový systém vykreslený pomocí systému LÖVE. Na částice sice nepůsobí gravitační síla, ale jejich radiální zrychlení je záporné, tj. částice jsou přitahovány zpět ke středu částicového systému.

5. Parametry částicového systému

Po vytvoření částicového systému výše popsanou funkcí love.graphics.newParticleSystem() je možné parametry částicového systému takřka libovolně měnit, spouštět či naopak zastavovat simulaci pohybu částic atd. V následující tabulce jsou vypsány některé vybrané metody ovlivňující parametry částicového systému – jedná se o metody použité v následujícím demonstračním příkladu:

# Metoda Význam
1 setEmmisionRate() Počet částic, které mají být vytvořeny (emitovány) za jednu sekundu. Skutečný počet emitovaných částic však může být nižší, v závislosti na jejich životnosti a maximálním povoleném počtu částic v systému.
2 setLifetime() Životnost celého systému částic. Pokud je překročena doba života částicového systému, přestane emitor vytvářet další částice. Lze nastavit i hodnotu -1, která znamená neomezenou dobu života částicového systému.
3 setParticleLife() Nastavení průměrné či minimální a maximální doby života částic. Buď je zadán pouze jeden údaj, který je chápán jako průměrná doba života částice v sekundách, nebo údaje dva – minimální a maximální doba, opět specifikovaná v sekundách.
4 setPosition() Specifikace souřadnic emitoru částic v rovině.
5 setDirection() Nastavení průměrné hodnoty úhlu, pod kterým částice vyletují ze svého zdroje (emitoru). Tento parametr má smysl nastavovat pouze v případě, že je rozptyl menší než 360°.
6 setSpread() Nastavení rozptylu vyletujících částic. Standardně je nastaven rozptyl 360°, tj. částice jsou emitovány do všech směrů.
7 setSpeed() Zadání průměrné, popř. minimální a maximální počáteční rychlosti částic.
8 setSizes() Nastavení relativní velikosti částice popř. její počáteční a koncové velikosti. Částice může v průběhu svého života měnit velikost – růst či se naopak zmenšovat. Hodnota 1 značí původní velikost rastrového obrázku s předlohou částice, 2 dvojnásobnou velikost atd.
9 start() Zapnutí emitoru částic. Po zavolání této metody vytváří emitor nové částice až do chvíle, než je zavolána metoda stop(), pause() či až do konce života částicového systému nastaveného metodou setLifetime().
10 stop() Vypnutí emitoru částic a vymazání interního časovače, pomocí kterého se testuje, zda již není překročena doba života částicového systému.
11 update() Po zavolání této metody se provede změna stavu částicového systému na základě jeho parametrů, tj. dojde k vytvoření (emitaci) nových částic, ke zrušení částic, které překročily dobu svého života i ke změně dalších parametrů částic (polohy, rychlosti, barvy, tvaru, natočení atd.). Tuto metodu je zapotřebí volat průběžně, ideálně z callback funkce draw() či update().

09

Obrázek 9: Částicové systémy je možné použít i pro vizualizaci různých fyzikálních simulací.

6. Demonstrační příklad číslo 13: jednoduchý částicový systém

Metody objektu typu ParticleSystem, o nichž jsme se zmínili v předchozí kapitole, jsou použity v dalším demonstračním příkladu. Po spuštění tohoto příkladu je částicový systém vytvořen a následně jsou nastaveny jeho základní parametry. Následně aplikace čeká na stisk klávesy [Enter], která slouží pro „nastartování“ částicového systému. Změna stavu částicového systému (vytvoření částic, zrušení starých částic, změna jejich polohy atd.) je provedena přibližně třicetkrát za sekundu v callback funkci love.update. Po stisku klávesy [Esc] se celá aplikace ukončí a zavře se její hlavní okno. Samotný částicový systém je představován emitorem umístěným ve středu obrazovky, z něhož vyletují částice na všechny strany (se stejnou pravděpodobností). Každá částice je představována obrázkem (spritem) globusu, který jsme využili i v demonstračních příkladech popsaných v předchozí části tohoto seriálu.

Podívejme se nyní na zdrojový kód tohoto demonstračního příkladu:

--
-- Knihovna LÖVE
--
-- Třináctý demonstrační příklad
--
-- Použití jednoduchého částicového systému.
--
 
 
-- rozměry okna, do něhož se bude provádět vykreslování
width = 450
height = 450
 
-- asociativní pole představující částicový systém
local particleSystem = nil
 
-- maximální počet částic v částicovém systému
particleCount = 1000
 
 
 
--
-- Funkce volaná při inicializaci aplikace.
--
function love.load()
    -- načtení standardního fontu a nastavení grafického režimu
    local font = love.graphics.newFont(love.default_font, 40)
 
    -- inicializace grafického režimu
    love.graphics.setMode(width, height, false, false, 0)
 
    -- nastavení fontu
    love.graphics.setFont(font)
 
    -- načtení obrázku představujícího jednu částici
    local particleImage = love.graphics.newImage("sprite1.png")
 
    -- vytvoření částicového systému s jeho inicializací
    particleSystem = love.graphics.newParticleSystem(particleImage, particleCount)
 
    -- kolik nových částic se průměrně vygeneruje za sekundu
    particleSystem:setEmissionRate(4)
 
    -- životnost emitoru částic i jednotlivých částic vytvářených v emitoru
    particleSystem:setLifetime(-1)
    particleSystem:setParticleLife(5)
 
    -- pozice emitoru na obrazovce
    particleSystem:setPosition(width/2, height/2)
 
    -- počáteční rychlost částic
    particleSystem:setSpeed(70, 100)
    particleSystem:setDirection(0)
    particleSystem:setSpread(360)
 
    -- další parametry systému
    particleSystem:setSizes(1)
    particleSystem:stop()
end
 
 
 
--
-- Funkce volaná cca 30x za sekundu
--
function love.update(dt)
    -- přepočítat parametry částicového systému
    particleSystem:update(dt)
 
    local delay = 1/30
    if dt < delay then
        love.timer.sleep(delay - dt)
    end
end
 
 
 
--
-- Tato funkce je volána automaticky při překreslení obsahu
-- okna či obrazovky.
--
function love.draw()
    -- režim vykreslování
    love.graphics.setBlendMode("alpha")
 
    -- vykreslení částicového systému na obrazovku
    love.graphics.draw(particleSystem, 0, 0)
 
    -- zprávy vypsané na obrazovky
    love.graphics.print("Press Enter to start particle emitter.", 30, 415)
    love.graphics.print("Press Escape to exit.", 30, 433)
end
 
 
 
--
-- Callback funkce zavolaná při stisku klávesy.
--
function love.keypressed(k)
    -- klávesou "Return" či "Enter" se částicový systém zapne
    if k == 'return' then
        particleSystem:start()
    end
    -- klávesou "Escape" se aplikace ukončí
    if k == 'escape' then
        love.event.quit()
    end
end
 
 
 
--
-- finito
--

10

Obrázek 10: Emitor částic je zastaven.

11

Obrázek 11: Začátek emitování částic.

12

Obrázek 12: Další stav částicového systému.

7. Změna základních parametrů částicového systému: gravitace, změna velikosti částic

V předchozím demonstračním příkladu byl emitor částic umístěn do středu obrazovky a částice z něj vylétaly ve všech směrech. Navíc na částice ani nepůsobila gravitace. Tento demonstrační příklad je samozřejmě možné upravit, a to hned několika způsoby. Asi největší změnou, která je po spuštění animace ihned viditelná, je nastavení gravitace, která má na částice působit. Vektor gravitační síly je orientován kolmo dolů a jeho velikost je určena metodou particleSystem:setGravity(min) popř. particleSystem:setGravity(min, max). Další ihned viditelnou změnou je nastavení proměnné velikosti částic metodou particleSystem:setSizes(size1, size2, …size8). Tato metoda je v příkladu volána se dvěma parametry představujícími počáteční a koncovou relativní velikost částic, kde hodnota 1 znamená původní velikost spritu a hodnota (například) 0.25 čtvrtinovou velikost spritu v porovnání s původní velikostí. Ve skutečnosti je však možné metodě particleSystem:setSizes() předat až osm relativních velikostí a vytvořit tak relativně složitý částicový systém.

13

Obrázek 13: Čtrnáctý demonstrační příklad: počáteční stav.

14

Obrázek 14: Čtrnáctý demonstrační příklad krátce po svém spuštění.

15

Obrázek 15: Další stav částicového systému.

8. Demonstrační příklad číslo 14: padající globusy

Změny, které byly popsány v sedmé kapitole, jsou součástí následujícího demonstračního příkladu, jenž po svém spuštění a stisku klávesy [Enter] zobrazí padající globusy. Toto chování je zajištěno jednoduchým způsobem – emitor částic totiž není umístěn v oblasti okna aplikace, ale nad tímto oknem, takže není vidět místo, v němž částice vznikají. Navíc mají částice díky vysoko umístěnému emitoru dostatek času na to, aby na ně začala působit gravitace, takže vzniká efekt patrný na obrázcích 14 a 15. Následuje výpis zdrojového kódu demonstračního příkladu:

--
-- Knihovna LÖVE
--
-- Čtrnáctý demonstrační příklad
--
-- Použití jednoduchého částicového systému na nějž působí gravitace.
--
 
 
-- rozměry okna, do něhož se bude provádět vykreslování
width = 450
height = 450
 
-- asociativní pole představující částicový systém
local particleSystem = nil
 
-- maximální počet částic v částicovém systému
particleCount = 1000
 
 
 
--
-- Funkce volaná při inicializaci aplikace.
--
function love.load()
    -- načtení standardního fontu a nastavení grafického režimu
    local font = love.graphics.newFont(love.default_font, 40)
 
    -- inicializace grafického režimu
    love.graphics.setMode(width, height, false, false, 0)
 
    -- nastavení fontu
    love.graphics.setFont(font)
 
    -- načtení obrázku představujícího jednu částici
    local particleImage = love.graphics.newImage("sprite1.png")
 
    -- vytvoření částicového systému s jeho inicializací
    particleSystem = love.graphics.newParticleSystem(particleImage, particleCount)
 
    -- kolik nových částic se průměrně vygeneruje za sekundu
    particleSystem:setEmissionRate(10)
 
    -- životnost emitoru částic i jednotlivých částic vytvářených v emitoru
    particleSystem:setLifetime(-1)
    particleSystem:setParticleLife(5)
 
    -- pozice emitoru na obrazovce (mimo obrazovku)
    particleSystem:setPosition(width/2, -50)
 
    -- počáteční rychlost částic
    particleSystem:setSpeed(70, 100)
    particleSystem:setDirection(0)
    particleSystem:setSpread(360)
 
    -- další parametry systému: gravitace působící na částice
    particleSystem:setGravity(100, 200)
    -- velikost částic a relativní změna velikosti v čase
    particleSystem:setSizes(1, 0.3)
    particleSystem:stop()
end
 
 
 
--
-- Funkce volaná cca 30x za sekundu
--
function love.update(dt)
    -- přepočítat parametry částicového systému
    particleSystem:update(dt)
 
    local delay = 1/30
    if dt < delay then
        love.timer.sleep(delay - dt)
    end
end
 
 
 
--
-- Tato funkce je volána automaticky při překreslení obsahu
-- okna či obrazovky.
--
function love.draw()
    -- režim vykreslování
    love.graphics.setBlendMode("alpha")
 
    -- vykreslení částicového systému na obrazovku
    love.graphics.draw(particleSystem, 0, 0)
 
    -- zprávy vypsané na obrazovky
    love.graphics.print("Press Enter to start particle emitter.", 30, 415)
    love.graphics.print("Press Escape to exit.", 30, 433)
end
 
 
 
--
-- Callback funkce zavolaná při stisku klávesy.
--
function love.keypressed(k)
    -- klávesou "Return" či "Enter" se částicový systém zapne
    if k == 'return' then
        particleSystem:start()
    end
    -- klávesou "Escape" se aplikace ukončí
    if k == 'escape' then
        love.event.quit()
    end
end
 
 
 
--
-- finito
--

9. Změna vlastností emitoru částic: počáteční směr a rozptyl

Připomeňme si, že nejdůležitějšími vlastnostmi emitoru částic je jeho poloha v ploše a dále pak směr „vystřelování“ nových částic. Poloha emitoru je určena jednoduše s využitím metody particleSystem:setPosition(x,y), což jsme si již ostatně ukázali na dvou příkladech. Směr vystřelování nových částic je určen metodami particleSystem:setDirection(úhel) a particleSystem:setSpread(úhel). Zatímco úhel předaný první z těchto metod reprezentuje směr, kterým je emitor obrácen (resp. přesněji řečeno směr jeho osy), tak úhel předaný druhé metodě reprezentuje rozptyl částic. Emitor částic si totiž můžeme představit jako reflektor, který můžeme libovolně natáčet a navíc můžeme měnit i rozptyl paprsku, a to od 0° do celých 360° (jen si musíme dát pozor na to, že velikosti všech úhlů se musí zadávat nikoli ve stupních, ale v radiánech).

16

Obrázek 16: Patnáctý demonstrační příklad: počáteční stav.

17

Obrázek 17: Patnáctý demonstrační příklad krátce po svém spuštění.

18

Obrázek 18: Další stav částicového systému.

10. Demonstrační příklad číslo 15: ohnivý déšť

Změna směru emitování nových částic i rozptylu těchto částic je použita v patnáctém demonstračním příkladu pro vytvoření iluze ohnivého deště. Emitor je umístěn na plochu okna, takže uživatelé mohou vidět místo, kde částice vznikají, Namísto obrázku (spritu) globusu je zde použit poněkud odlišný obrázek, jehož pixely mají rozdílnou průhlednost, což díky nastavení míchacího režimu (blend mode) vede k tomu, že se intenzity barev jednotlivých částic slévají. Podívejme se na zdrojový kód tohoto (dnes již předposledního) příkladu:

--
-- Knihovna LÖVE
--
-- Patnáctý demonstrační příklad
--
-- Použití jednoduchého částicového systému.
--
 
 
-- rozměry okna, do něhož se bude provádět vykreslování
width = 450
height = 450
 
-- asociativní pole představující částicový systém
local particleSystem = nil
 
-- maximální počet částic v částicovém systému
particleCount = 1000
 
 
 
--
-- Funkce volaná při inicializaci aplikace.
--
function love.load()
    -- načtení standardního fontu a nastavení grafického režimu
    local font = love.graphics.newFont(love.default_font, 40)
 
    -- inicializace grafického režimu
    love.graphics.setMode(width, height, false, false, 0)
 
    -- nastavení fontu
    love.graphics.setFont(font)
 
    -- načtení obrázku představujícího jednu částici
    local particleImage = love.graphics.newImage("particle.png")
 
    -- vytvoření částicového systému s jeho inicializací
    particleSystem = love.graphics.newParticleSystem(particleImage, particleCount)
 
    -- kolik nových částic se průměrně vygeneruje za sekundu
    particleSystem:setEmissionRate(100)
 
    -- životnost emitoru částic i jednotlivých částic vytvářených v emitoru
    particleSystem:setLifetime(-1)
    particleSystem:setParticleLife(3)
 
    -- počáteční rychlost částic
    particleSystem:setSpeed(100, 400)
 
    -- další parametry systému: gravitace působící na částice, změna barvy apod.
    particleSystem:setGravity(200,500)
    particleSystem:setColors(255, 255, 0, 255, 255, 0, 0, 255)
 
    -- pozice emitoru částic, směr generování částic a rozptyl
    particleSystem:setPosition(width/2, 50)
    particleSystem:setDirection(3.14/2)
    particleSystem:setSpread(0.3)
 
    -- další parametry systému: gravitace působící na částice
    particleSystem:setGravity(100, 200)
    -- velikost částic a relativní změna velikosti v čase
    particleSystem:setSizes(1, 0.3)
    particleSystem:stop()
end
 
 
 
--
-- Funkce volaná cca 30x za sekundu
--
function love.update(dt)
    -- přepočítat parametry částicového systému
    particleSystem:update(dt)
 
    local delay = 1/30
    if dt < delay then
        love.timer.sleep(delay - dt)
    end
end
 
 
 
--
-- Tato funkce je volána automaticky při překreslení obsahu
-- okna či obrazovky.
--
function love.draw()
    -- režim vykreslování
    love.graphics.setBlendMode("alpha")
 
    -- vykreslení částicového systému na obrazovku
    love.graphics.draw(particleSystem, 0, 0)
 
    -- zprávy vypsané na obrazovky
    love.graphics.print("Press Enter to start particle emitter.", 30, 415)
    love.graphics.print("Press Escape to exit.", 30, 433)
end
 
 
 
--
-- Callback funkce zavolaná při stisku klávesy.
--
function love.keypressed(k)
    -- klávesou "Return" či "Enter" se částicový systém zapne
    if k == 'return' then
        particleSystem:start()
    end
    -- klávesou "Escape" se aplikace ukončí
    if k == 'escape' then
        love.event.quit()
    end
end
 
 
 
--
-- finito
--

11. Změna barvy a rotace emitovaných částic

Dalším důležitým parametrem částicového systému je barva částic, která může být – podobně jako jejich velikost – v čase proměnná. Nastavení barvy se provádí metodou particleSystem:setColors( r1, g1, b1, a1, r2, g2, b2, a2, …, r8, g8, b8, a8 ). Jak je z hlavičky této funkce patrné, lze jí předat až osm barev, resp. přesněji řečeno osm trojic představujících barvové složky červená+zelená+modrá a průhlednost aplikovanou na všechny pixely. Posledním parametrem částicového systému, o němž se dnes zmíníme, je rotace částic (neboli spin), který lze zadat metodou particleSystem:setSpin(). Předávaný parametr udává úhel rotace částice (v radiánech) za sekundu; tj. čím vyšší hodnota je předána, tím rychleji částice rotují. Oba tyto parametry jsou použity v dnešním posledním příkladu, který po svém spuštění vytvoří tuto animaci:

19

Obrázek 19: Šestnáctý demonstrační příklad krátce po svém spuštění.

20

Obrázek 20: Pokračování výbuchu.

21

Obrázek 21: Pokračování výbuchu.

12. Demonstrační příklad číslo 16: výbuch

Zatímco v patnáctém příkladu byly částice emitovány směrem dolů a vytvářely tak představu ohnivého deště, v příkladu šestnáctém směřuje počáteční vektor pohybu částic směrem nahoru (tj. vlastně proti gravitaci). Tímto způsobem lze vytvořit iluzi výbuchu. Barva částic je proměnná – od sytě žluté po červenou. Částice taktéž rotují, což celou simulaci dále vylepšuje. Opět se podívejme na zdrojový kód, který se příliš neliší od předchozích příkladů:

--
-- Knihovna LÖVE
--
-- Šestnáctý demonstrační příklad
--
-- Použití jednoduchého částicového systému.
--
 
 
-- rozměry okna, do něhož se bude provádět vykreslování
width = 450
height = 450
 
-- asociativní pole představující částicový systém
local particleSystem = nil
 
-- maximální počet částic v částicovém systému
particleCount = 1000
 
 
 
--
-- Funkce volaná při inicializaci aplikace.
--
function love.load()
    -- načtení standardního fontu a nastavení grafického režimu
    local font = love.graphics.newFont(love.default_font, 40)
 
    -- inicializace grafického režimu
    love.graphics.setMode(width, height, false, false, 0)
 
    -- nastavení fontu
    love.graphics.setFont(font)
 
    -- načtení obrázku představujícího jednu částici
    local particleImage = love.graphics.newImage("particle.png")
 
    -- vytvoření částicového systému s jeho inicializací
    particleSystem = love.graphics.newParticleSystem(particleImage, particleCount)
 
    -- kolik nových částic se průměrně vygeneruje za sekundu
    particleSystem:setEmissionRate(200)
 
    -- životnost emitoru částic i jednotlivých částic vytvářených v emitoru
    particleSystem:setLifetime(-1)
    particleSystem:setParticleLife(3)
 
    -- počáteční rychlost částic
    particleSystem:setSpeed(100, 400)
 
    -- další parametry systému: gravitace působící na částice, změna barvy apod.
    particleSystem:setGravity(200,500)
    particleSystem:setColors(255, 255, 0, 100, 255, 0, 0, 100)
 
    -- pozice emitoru částic, směr generování částic a rozptyl
    particleSystem:setPosition(width/2, height)
    particleSystem:setDirection(-3.14/2)
    particleSystem:setSpread(0.3)
    particleSystem:setSpin(1, 3)
 
    -- další parametry systému: gravitace působící na částice
    particleSystem:setGravity(100, 200)
 
    -- velikost částic a relativní změna velikosti v čase
    particleSystem:setSizes(3, 0.5)
    particleSystem:stop()
end
 
 
 
--
-- Funkce volaná cca 30x za sekundu
--
function love.update(dt)
    -- přepočítat parametry částicového systému
    particleSystem:update(dt)
 
    local delay = 1/30
    if dt < delay then
        love.timer.sleep(delay - dt)
    end
end
 
 
 
--
-- Tato funkce je volána automaticky při překreslení obsahu
-- okna či obrazovky.
--
function love.draw()
    -- režim vykreslování
    love.graphics.setBlendMode("alpha")
 
    -- vykreslení částicového systému na obrazovku
    love.graphics.draw(particleSystem, 0, 0)
 
    -- zprávy vypsané na obrazovky
    love.graphics.print("Press Enter to start particle emitter.", 30, 415)
    love.graphics.print("Press Escape to exit.", 30, 433)
end
 
 
 
--
-- Callback funkce zavolaná při stisku klávesy.
--
function love.keypressed(k)
    -- klávesou "Return" či "Enter" se částicový systém zapne
    if k == 'return' then
        particleSystem:start()
    end
    -- klávesou "Escape" se aplikace ukončí
    if k == 'escape' then
        love.event.quit()
    end
end
 
 
 
--
-- finito
--

13. Repositář se zdrojovými kódy dnešních demonstračních příkladů

Všech pět demonstračních příkladů, s nimiž jsme se v dnešním
článku seznámili, bylo uloženo do Git repositáře na GitHubu (https://github.com/tisnik/presentations).
Každý demonstrační příklad obsahuje jak zdrojový kód main.lua,
tak i sprity potřebné pro jeho spuštění:

# Příklad Zdrojový kód
1 example12 https://github.com/tisnik/presentations/tree/master/love/example12
2 example13 https://github.com/tisnik/presentations/tree/master/love/example13
3 example14 https://github.com/tisnik/presentations/tree/master/love/example14
4 example15 https://github.com/tisnik/presentations/tree/master/love/example15
5 example16 https://github.com/tisnik/presentations/tree/master/love/example16

14. Odkazy na Internetu

  1. Particle Systems From the Ground Up
    http://buildnewgames.com/particle-systems/
  2. Particle Systems
    http://natureofcode.com/book/chapter-4-particle-systems/
  3. Domovská stránka systému LÖVE
    http://love2d.org/
  4. Dokumentace k systému LÖVE
    http://love2d.org/wiki/love
  5. Domovská stránka programovacího jazyka Lua
    http://www.lua.org/
  6. Seriál o programovacím jazyku Lua (root.cz):
    http://www.root.cz/serialy/programovaci-jazyk-lua/
  7. Domovská stránka systému LÖVE
    http://love2d.org/
  8. Domovská stránka programovacího jazyka Lua
    http://www.lua.org/
  9. Web o Lieru, Gusanos, GeneRally, Atari atd.
    http://karelik.wz.cz/
  10. Web o Lieru, Gusanos
    http://karelik.wz.cz/gusanos.php
  11. GUSANOS
    http://gusanos.sourceforge.net/
  12. GUSANOS Download
    http://sourceforge.net/projects/gusanos/
  13. Lua
    http://www.linuxexpres.cz/praxe/lua
  14. Lua
    http://cs.wikipedia.org/wiki/Lua
  15. Lua (programming language)
    http://en.wikipedia.org/wiki/Lua_(programming_language)
  16. The Lua Programming Language
    http://www.tiobe.com/index.php/paperinfo/tpci/Lua.html
  17. Lua Programming Gems
    http://www.lua.org/gems/
  18. LuaForge
    http://luaforge.net/
  19. Forge project tree
    http://luaforge.net/softwaremap/trove_list.php
  20. SdlBasic home page
    http://www.sdlbasic.altervista.org/main/
  21. SdlBasic examples
    http://nitrofurano.linuxkafe.com/sdlbasic/
  22. SdlBasic na Wikipedii
    http://en.wikipedia.org/wiki/SdlBasic
  23. Simple DirectMedia Layer
    http://en.wikipedia.org/wiki/Simple_DirectMedia_Layer
  24. SDLBASIC – The high-level interpreter for all?
    http://openbytes.wordpress.com/2008/11/08/sdlbasic-the-high-level-interpreter-for-all/
  25. FreeBasic home page
    http://www.freebasic.net/
  26. FreeBASIC (Wikipedia EN)
    https://en.wikipedia.org/wiki/FreeBASIC
  27. FreeBASIC Wiki
    http://www.freebasic.net/wiki/wikka.php?wakka=FBWiki
  28. FreeBASIC Manual
    http://www.freebasic.net/wiki/wikka.php?wakka=DocToc
  29. FreeBASIC (Wikipedia CZ)
    http://cs.wikipedia.org/wiki/FreeBASIC
  30. The Griffon Legend
    http://syn9.thingie.net/?table=griffonlegend
  31. Seriál Letní škola programovacího jazyka Logo
    http://www.root.cz/serialy/letni-skola-programovaciho-jazyka-logo/
  32. Scratch: oficiální stránka projektu
    http://scratch.mit.edu/
  33. Scratch: galerie projektů vytvořených ve Scratchi
    http://scratch.mit.edu/galleries/browse/newest
  34. Scratch: nápověda
    file:///usr/share/scratch/Help/en/index.html
  35. Scratch: obrazovky nápovědy
    file:///usr/share/scratch/Help/en/allscreens.html
  36. Scratch (Wikipedie CZ)
    http://cs.wikipedia.org/wiki/Scratch
  37. Scratch (programming language)
    http://en.wikipedia.org/wiki/Scratch_(programming_language)
  38. Scratch Modification
    http://wiki.scratch.mit.edu/wiki/Scratch_Modification
  39. Scratch Lowers Resistance to Programming
    http://www.wired.com/gadgetlab/2009/03/scratch-lowers/
  40. Snap!
    http://snap.berkeley.edu/
  41. Prostředí Snap!
    http://snap.berkeley.edu/snapsource/snap.html
  42. Alternatives to Scratch
    http://wiki.scratch.mit.edu/wiki/Alternatives_to_Scratch
  43. Basic-256 home page
    http://www.basic256.org/index_en
  44. Basic-256 Language Documentation
    http://doc.basic256.org/doku.php
  45. Basic-256 Art Gallery
    http://www.basic256.org/artgallery
  46. Basic-256 Tutorial
    http://www.basic256.org/tutorials
  47. Why BASIC?
    http://www.basic256.org/whybasic
  48. A book to teach ANYBODY how to program a computer (using BASIC)
    http://www.basicbook.org/
  49. BASIC Computer Games (published 1978) – Hammurabi
    http://atariarchives.org/basicgames/showpage.php?page=78
  50. Hamurabi – zdrojový kód v BASICu
    http://www.dunnington.u-net.com/public/basicgames/HMRABI

15. Literatura, v níž jsou zmíněny částicové systémy

  1. Arvo James (editor):
    Graphics Gems II,
    Academic Press, 1991, ISBN 0-120-54481-9
  2. Baraff David and Witkin Andrew:
    Physically Based Modeling,
    SIGGRAPH Course Notes, July 1998, pages B1–C12
  3. Beer and Johnson:
    Vector Mechanics for Engineers: Dynamics,
    Sixth Edition, WCB/McGraw-Hill, New York, 1997, ISBN 0-07121-828-9
  4. Beneš B., Felkel P., Sochor J. and Žára J.:
    Vizualizace
    Skripta ČVUT, Praha, 1997
  5. Benson Richard:
    Particle Systems,
    PowerPoint Presentation, 2002
  6. Blinn J. F.:
    Light Reflection Functions for Simulation of Clouds and Dusty surfaces,
    Computer Graphics 16(3), 1982, pages 21–29
  7. Blinn J. F.:
    Jim Blin’s Corner: Dirty Pixels,
    Morgan Kaufmann, 1996, ISBN 1-558-60455-3
  8. Foley J., Dam van A., Feiner S., Hughes J.:
    Computer Graphics – Principles and Practice (Second Edition),
    Addison-Wesley, Reading, Massachusetts, 1990, ISBN 0-201-12110-7
  9. Hausen Ch.:
    Visualization of Vector Fields (2D and 3D),
    tutorial, National Laboratory, Los Alamos, 1993
  10. Intarrante V. and Grosch Ch.:
    Visualizing 3D Flow,
    IEEE Computer graphics and Applications, July 1998, pages 49–53
  11. Landers, J.:
    The Ocean Spray in Your Face,
    Game Developer, Volume 5, Number 7, July 1998, pages 13–15.
  12. Loke T., Tan D., Seah H. and Er M.:
    Rendering Fireworks Displays,
    IEEE Computer Graphics & Applications, May 1992, Volume 12, Number 3, pages 33–43
  13. Magnetat-Thalmann B., Thalmann D. and Arnaldi B.:
    Computer Animation and Simulation 2000,
    Springer Verlag, Wien, ISBN 3-2118-3549-0
  14. Max N., Crawfis R. and Williams D.:
    Visualization for climate Modeling,
    IEEE Computer graphics and Applications, July 1993, pages 34–40
  15. Reeves William T.:
    Particle Systems – A Technique for Modeling a Class of Fuzzy objects,
    Computer Graphics vol.17, Number 3, July 1983, pages 359–376
  16. Reeves William T. and Blau R.:
    Approximate and Probabilistic Algorithms for Shading and Rendering Structured Particle System,
    Proceedings of SIGGRAPH 1985, Volume 19(3), 1985, pages 313–322
  17. Rhudy R.:
    Rendering Particle Systems Fast and Accurately,
    (listopad 2002)
  18. Sims K.:
    Particle Animation and Rendering Using Data Parallel Computation,
    Computer Graphics (SIGGRAPH ’90), Volume 24, Number 4, August 1990, pages 405–413
  19. Stalling D. et al.:
    Fast Display of Illuminated Field Lines,
    IEEE Transactions of Visualization and Computer Graphics, Volume 3, April 1997, pages 118–127
  20. Wijk van J.J:
    Flow Visualization with Surface Particles,
    IEEE Computer Graphics & Applications, July 1993, pages 19–24
  21. Wijk van J.J, Hin A. J. S., de Leeuw W. C., Post F. H.:
    Three Ways to Show 3D Fluid Flow,
    IEEE Computer Graphics \& Applications, September 1994, pages 33–39