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ů
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.
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]
Obrázek 2: Scéna vykreslená demonstračním příkladem.
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).
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
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ě).
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.
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.
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(). |
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 --
Obrázek 10: Emitor částic je zastaven.
Obrázek 11: Začátek emitování částic.
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.
Obrázek 13: Čtrnáctý demonstrační příklad: počáteční stav.
Obrázek 14: Čtrnáctý demonstrační příklad krátce po svém spuštění.
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).
Obrázek 16: Patnáctý demonstrační příklad: počáteční stav.
Obrázek 17: Patnáctý demonstrační příklad krátce po svém spuštění.
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:
Obrázek 19: Šestnáctý demonstrační příklad krátce po svém spuštění.
Obrázek 20: Pokračování výbuchu.
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
- Particle Systems From the Ground Up
http://buildnewgames.com/particle-systems/ - Particle Systems
http://natureofcode.com/book/chapter-4-particle-systems/ - Domovská stránka systému LÖVE
http://love2d.org/ - Dokumentace k systému LÖVE
http://love2d.org/wiki/love - Domovská stránka programovacího jazyka Lua
http://www.lua.org/ - Seriál o programovacím jazyku Lua (root.cz):
http://www.root.cz/serialy/programovaci-jazyk-lua/ - Domovská stránka systému LÖVE
http://love2d.org/ - Domovská stránka programovacího jazyka Lua
http://www.lua.org/ - Web o Lieru, Gusanos, GeneRally, Atari atd.
http://karelik.wz.cz/ - Web o Lieru, Gusanos
http://karelik.wz.cz/gusanos.php - GUSANOS
http://gusanos.sourceforge.net/ - GUSANOS Download
http://sourceforge.net/projects/gusanos/ - Lua
http://www.linuxexpres.cz/praxe/lua - Lua
http://cs.wikipedia.org/wiki/Lua - Lua (programming language)
http://en.wikipedia.org/wiki/Lua_(programming_language) - The Lua Programming Language
http://www.tiobe.com/index.php/paperinfo/tpci/Lua.html - Lua Programming Gems
http://www.lua.org/gems/ - LuaForge
http://luaforge.net/ - Forge project tree
http://luaforge.net/softwaremap/trove_list.php - SdlBasic home page
http://www.sdlbasic.altervista.org/main/ - SdlBasic examples
http://nitrofurano.linuxkafe.com/sdlbasic/ - SdlBasic na Wikipedii
http://en.wikipedia.org/wiki/SdlBasic - Simple DirectMedia Layer
http://en.wikipedia.org/wiki/Simple_DirectMedia_Layer - SDLBASIC – The high-level interpreter for all?
http://openbytes.wordpress.com/2008/11/08/sdlbasic-the-high-level-interpreter-for-all/ - FreeBasic home page
http://www.freebasic.net/ - FreeBASIC (Wikipedia EN)
https://en.wikipedia.org/wiki/FreeBASIC - FreeBASIC Wiki
http://www.freebasic.net/wiki/wikka.php?wakka=FBWiki - FreeBASIC Manual
http://www.freebasic.net/wiki/wikka.php?wakka=DocToc - FreeBASIC (Wikipedia CZ)
http://cs.wikipedia.org/wiki/FreeBASIC - The Griffon Legend
http://syn9.thingie.net/?table=griffonlegend - Seriál Letní škola programovacího jazyka Logo
http://www.root.cz/serialy/letni-skola-programovaciho-jazyka-logo/ - Scratch: oficiální stránka projektu
http://scratch.mit.edu/ - Scratch: galerie projektů vytvořených ve Scratchi
http://scratch.mit.edu/galleries/browse/newest - Scratch: nápověda
file:///usr/share/scratch/Help/en/index.html - Scratch: obrazovky nápovědy
file:///usr/share/scratch/Help/en/allscreens.html - Scratch (Wikipedie CZ)
http://cs.wikipedia.org/wiki/Scratch - Scratch (programming language)
http://en.wikipedia.org/wiki/Scratch_(programming_language) - Scratch Modification
http://wiki.scratch.mit.edu/wiki/Scratch_Modification - Scratch Lowers Resistance to Programming
http://www.wired.com/gadgetlab/2009/03/scratch-lowers/ - Snap!
http://snap.berkeley.edu/ - Prostředí Snap!
http://snap.berkeley.edu/snapsource/snap.html - Alternatives to Scratch
http://wiki.scratch.mit.edu/wiki/Alternatives_to_Scratch - Basic-256 home page
http://www.basic256.org/index_en - Basic-256 Language Documentation
http://doc.basic256.org/doku.php - Basic-256 Art Gallery
http://www.basic256.org/artgallery - Basic-256 Tutorial
http://www.basic256.org/tutorials - Why BASIC?
http://www.basic256.org/whybasic - A book to teach ANYBODY how to program a computer (using BASIC)
http://www.basicbook.org/ - BASIC Computer Games (published 1978) - Hammurabi
http://atariarchives.org/basicgames/showpage.php?page=78 - 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
- Arvo James (editor):
Graphics Gems II,
Academic Press, 1991, ISBN 0-120-54481-9 - Baraff David and Witkin Andrew:
Physically Based Modeling,
SIGGRAPH Course Notes, July 1998, pages B1–C12 - Beer and Johnson:
Vector Mechanics for Engineers: Dynamics,
Sixth Edition, WCB/McGraw-Hill, New York, 1997, ISBN 0-07121-828-9 - Beneš B., Felkel P., Sochor J. and Žára J.:
Vizualizace
Skripta ČVUT, Praha, 1997 - Benson Richard:
Particle Systems,
PowerPoint Presentation, 2002 - Blinn J. F.:
Light Reflection Functions for Simulation of Clouds and Dusty surfaces,
Computer Graphics 16(3), 1982, pages 21–29 - Blinn J. F.:
Jim Blin's Corner: Dirty Pixels,
Morgan Kaufmann, 1996, ISBN 1-558-60455-3 - 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 - Hausen Ch.:
Visualization of Vector Fields (2D and 3D),
tutorial, National Laboratory, Los Alamos, 1993 - Intarrante V. and Grosch Ch.:
Visualizing 3D Flow,
IEEE Computer graphics and Applications, July 1998, pages 49–53 - Landers, J.:
The Ocean Spray in Your Face,
Game Developer, Volume 5, Number 7, July 1998, pages 13–15. - 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 - Magnetat-Thalmann B., Thalmann D. and Arnaldi B.:
Computer Animation and Simulation 2000,
Springer Verlag, Wien, ISBN 3-2118-3549-0 - Max N., Crawfis R. and Williams D.:
Visualization for climate Modeling,
IEEE Computer graphics and Applications, July 1993, pages 34–40 - 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 - 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 - Rhudy R.:
Rendering Particle Systems Fast and Accurately,
(listopad 2002) - Sims K.:
Particle Animation and Rendering Using Data Parallel Computation,
Computer Graphics (SIGGRAPH '90), Volume 24, Number 4, August 1990, pages 405–413 - Stalling D. et al.:
Fast Display of Illuminated Field Lines,
IEEE Transactions of Visualization and Computer Graphics, Volume 3, April 1997, pages 118–127 - Wijk van J.J:
Flow Visualization with Surface Particles,
IEEE Computer Graphics & Applications, July 1993, pages 19–24 - 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