Magazín KPI

№ 2 / december 2017

Babylon.js

Babylon.js je softvérový rámec pre vývoj 3D hier, založený na programovacom jazyku JavaScript, HTML5 a grafickej knižnici WebGL. Ide o open source nástroj, ktorý vďaka svojim zabudovaným vlastnostiam umožňuje rýchlu implementáciu 3D funkcionality. Článok predstavuje jeho základy pomocou vytvorenia jednoduchej počítačovej hry.


Podľa oficiálnej dokumentácie má Babylon.js tri základné charakteristiky:

  • “Easy Setup” – Nič nie je potrebné inštalovať pre vývoj programov s Babylon.js a nič nie je potrebné inštalovať na klientskom počítači na spustenie vášho programu.
  • WebGL – Základom je webová grafická knižnica WebGL, ktorá umožňuje vykresľovanie interaktívnej 3D grafiky v ľubovoľnom kompatibilnom webovom prehliadači bez nutnosti inštalácie ďalších doplnkov. WebGL používa HTML5 prvok canvas a je prístupný pomocou rozhrania DOM.
  • JavaScript – Babylon.js je založený na dynamickom skriptovacom jazyku JavaScript, ktorý má prvotriedne funkcie a je široko používaný na strane klienta (niekedy aj na strane servera).

V tomto tutoriáli predstavíme základy používania rámca Babylon.js na príklade jednoduchej počítačovej hry, ktorú spolu vytvoríme. Hráč letí na lietajúcom tanieri vesmírom a cestou stretáva planéty a meteority. Pohyb môže ovládať pomocou šípiek. V nádrži má obmedzené množstvo paliva, ktoré mu stále ubúda. Rádioaktívne meteority však môžu byť vhodným palivom, stačí sa ich lietajúcim tanierom dotknúť. Hráč musí dávať pozor na planéty, lebo zrážka s nimi zapríčiní výbuch a ten bude znamenať koniec hry. Scéna hry bude vyzerať približne takto:

Pripravme si prostredie

Budeme potrebovať tieto softvérové nástroje:

  • Vhodný textový editor na písanie programového kódu.
  • Webový prehliadač s podporou WebGL. Ak si nie sme istí, podporu WebGL nášho prehliadača si môžeme otestovať.
  • Webový server, z ktorého budeme načítavať všetko príslušenstvo k hre. Webový server je nevyhnutný, ak chceme používať rôzne externé zdroje alebo vlastné 3D objekty, napríklad .babylon súbory. Tie sú obvykle načítavané pomocou XHR, a to si vyžaduje webový server. V našej hre použijeme pozadie a viaceré textúry. Ako webový server môžeme použiť voľne dostupný Apache httpd.

Na webovom serveri vytvoríme adresár space_flight s podadresármi:

  • assets – adresár bude obsahovať pomocné súbory s obrázkami, textúrami, pozadím, zvukmi a podobne,
  • css – adresár s použitými kaskádnymi štýlmi,
  • js – adresár s kódom napísaným v jazyku JavaScript.

Stiahneme si najnovšiu verziu skriptu babylon.js a umiestnime súbor do adresára js. Do tohoto adresára si pripravíme aj zatiaľ prázdny súbor initScene.js, ktorý bude obsahovať nami vytvorené skripty v jazyku JavaScript.

V pracovnom adresári space_flight vytvoríme súbor index.html. Keďže väčšina nášho kódu bude napísaná v jazyku JavaScript, HTML súbor bude veľmi jednoduchý:

<html>
<head>
    <meta http-equiv charset="utf-8">
    <link rel="stylesheet" type="text/css" href="css/style.css" />
        <!-- Najnovšia verzia skriptu babylon.js -->
    <script src="js/babylon.2.6.js"></script>
    <script src="js/initScene.js"></script>
</head>
<body>
    <canvas id="renderCanvas"></canvas>
</body>
</html>

V tele sa nachádza najdôležitejší HTML5 element canvas – kresliace plátno, na ktorom sa bude odohrávať naša hra.

Do adresára css vložíme jednoduchý súbor style.css s kaskádnymi štýlmi, v ktorom je element canvas nakonfigurovaný tak, aby zaberal celé okno.

html, body {
    height: 100%;
    width: 100%;
    padding: 0;
    margin: 0;
}
#renderCanvas {
    width: 100%;
    height: 100%;
    margin: 0px;
    padding: 0px;
}

Môžeme začať

Teraz začneme písať kód v jazyku JavaScript do súboru initScene.js. Predtým, ako sa urobí čokoľvek iné, musí byť načítaný DOM. Preto zabalíme štartovaciu funkciu onload() do event handlera DOMContentLoaded, aby sme si boli istí, že celý DOM sa načíta ihneď na začiatku. Do súboru teda vložíme riadky:

// funkcia onload bude nacitana, az ked bol nacitany DOM
document.addEventListener("DOMContentLoaded", onload, false);

A môžeme začať vytvárať štartovaciu funkciu onload(). Úplne na začiatok súboru initScene.js pridáme deklarácie nasledovných globálnych premenných:

// deklaracia premennych canvas, engine, scene
var canvas, engine, scene;

Dva základné objekty nevyhnutné pre fungovanie hry sú canvas a engine. Najprv musíme získať referenciu na canvas. Keďže je to HTML element, nájdeme ho podľa identifikátora pomocou metódy getElementById(), ktorej parametrom je identifikačný reťazec renderCanvas. Pokračujeme vytvorením nového objektu engine pre canvas. Je to najdôležitejší objekt, na ktorom je postavený rámec Babylon.js. Funguje ako prostredník medzi WebGL a Babylon.js. Začiatok tela funkcie onload() budú tvoriť riadky:

// vytvorenie canvas a engine
canvas = document.getElementById("renderCanvas");
engine = new BABYLON.Engine(canvas, true);

Hodnota true druhého parametra konštruktora pre engine znamená aktivovanie vyhladenia kriviek (antialiasing). Kým v reálnom svete vidíme, že veci majú hladké línie a krivky, pri vykresľovaní obrázkov na obrazovku sú obrázky rozdelené do pixelov v tvare malých štvorčekov. Výsledkom tohto procesu je, že línie a krivky sú často zubaté. Zapnutie parametra pre aktivovanie vyhladenia bude redukovať tento problém.

Ďalším dôležitým objektom hry je herná scéna. Jedna hra môže mať aj viacero scén a dá sa medzi nimi prepínať, preto objekt pre scénu uložíme do globálnej premennej scene. Na toto miesto funkcie onload() umiestnime volanie funkcie initScene(), ktorá bude slúžiť na vytvorenie a inicializáciu scény. Samotnú funkciu initScene() vytvoríme neskôr.

Dôležitou súčasťou štartovacej funkcie onload() je spustenie hernej slučky, ktorá bude opakovane vykresľovať scénu scene na kresliacom plátne (rendering), a to rýchlosťou 60-krát za sekundu. Príliš veľa kódu v tejto funkcii môže zapríčimiť oneskorenie zobrazovania jednotlivých snímkov.

// spustenie hernej slucky
engine.runRenderLoop(function () {
    scene.render();
});

Základ štartovacej funkcie je hotový. Teraz ešte za funkciu onload() pridáme event handler pre obsluhu zmeny veľkosti okna prehliadača, aby sa veľkosť kresliaceho plátna prispôsobila veľkosti okna. Táto časť je nepovinná, ale veľmi užitočná.

// prisposobenie velkosti babylon engine velkosti okna
window.addEventListener("resize", function () {
    if (engine) {
        engine.resize();
    }
},false);

Začiatok máme za sebou, celý obsah súboru initScene.js zatiaľ vyzerá takto:

// deklaracia premennych canvas, engine, scene
var canvas, engine, scene;

// funkcia onload bude nacitana, az ked bol nacitany DOM
document.addEventListener("DOMContentLoaded", onload, false);

// funkcia onload, ktora vytvori babylon engine a scene
var onload = function () {

    // vytvorenie canvas a engine
    canvas = document.getElementById("renderCanvas");
    engine = new BABYLON.Engine(canvas, true);

    // volanie funkcie na vytvorenie sceny
    initScene();

    // spustenie hernej slucky
    engine.runRenderLoop(function () {
        scene.render();
    });

};

// prisposobenie velkosti babylon engine velkosti okna
window.addEventListener("resize", function () {
    if (engine) {
        engine.resize();
    }
},false);

Scéna

Vytvoríme funkciu initScene(). Najprv do premennej scene vložíme nový objekt triedy Scene. K scéne patrí kamera a svetlá. Tu však bude potrebné určiť ich pozíciu, a preto sa zmienime o súradnicovej sústave v Babylon.js.

Používa sa ľavotočivá trojrozmerná sústava súradníc. To znamená, že kladná časť osi x smeruje doprava, kladná časť osi y nahor a kladná časť osi z dopredu, ako ukazuje obrázok (zdroj):

Kamera

Do globálnej premennej camera priradíme nový objekt triedy FreeCamera. Parametre konštruktora sú názov kamery, jej pozícia v trojrozmernom priestore a scéna. Naša kamera je v ukážke kódu uvedenom nižšie umiestnená na pozícii (x, y, z) = (0, 5, -30) a jej cieľový bod je (0, 0, 20). Kameru je možné riadiť pomocou šípiek na klávesnici a myšou. Riadenie je aktivované metódou attachControl(). Nezabudnime pridať deklaráciu premennej camera k ostatným deklaráciám na začiatku súboru.

Babylon.js podporuje viacero typov kamier, o ktorých sa môže čitateľ podrobnejšie dozvedieť v oficiálnom tutoriáli Babylon.js v časti Cameras (Kamery).

Svetlá

Nevyhnutnou súčasťou scény je osvetlenie. Ak nepridáme do scény svetlá, všetky objekty na scéne budú čierne.

V ukážke použijeme svetlá dvoch druhov. Hemisférické svetlo simuluje svetlo okolitého prostredia a je definované smerom k oblohe, čo mimochodom nemusí byť vždy hore. Tento smer je daný druhým argumentom v konštruktore. Hemisférické svetlo je mäkké a nevrhá tiene. Smerové svetlo je určené smerom, kam smeruje (druhý argument v konštruktore). Je vysielané akoby zovšadiaľ. Okrem spomínaných typov svetiel podporuje Babylon.js aj ďalšie, popísané v časti Lights (Svetlá) tutoriálu oficiálnej stránky produktu.

Svetlám je možné nastaviť rôzne vlastnosti, ako intenzitu, pozíciu, ale aj farbu difúzneho a spekulárneho odrazu (Phong reflection model). Farba je objektom triedy Color3. Konštruktor tejto triedy má trojicu argumentov (r, g, b), každý z intervalu od 0 do 1. Ako naznačuje označenie argumentov, používa sa farebný model RGB. Ak chceme použiť hodnoty z intervalu od 0 do 255, musíme vyvolať metódu FromInts().

Dosť bolo teórie! Tu je ukážka funkcie initScene():

// funkcia na vytvorenie sceny
var initScene = function() {
    scene = new BABYLON.Scene(engine);

    // priradenie kamery pre canvas
    camera = new BABYLON.FreeCamera("camera",
                         new BABYLON.Vector3(0, 5, -30), scene);
    camera.setTarget(new BABYLON.Vector3(0,0,20));
    camera.attachControl(canvas);

    // nastavenie osvetlenia sceny
    var light1 = new BABYLON.HemisphericLight("hemi", 
                             new BABYLON.Vector3(0, 0.5, 0), scene);
    light1.intensity = 0.6;

    var light2 = new BABYLON.DirectionalLight("dir", 
                             new BABYLON.Vector3(0,-0.5,0.5), scene);
    light2.position = new BABYLON.Vector3(0.1,100,-100);
    light2.intensity = 0.4;
    light2.diffuse = BABYLON.Color3.FromInts(204,196,255);
};

Teraz môžeme prvýkrát vyskúšať, ako vyzerá naša scéna. Do webového prehliadača zadáme URL http://localhost/space_flight/index.html. Po sputení uvidíme zatiaľ len prázdnu scénu s tmavým pozadím.

Útvary na scénu!

Teraz sa naučíme, ako sa v Babylon.js vytvárajú základné geometrické útvary. Je to veľmi jednoduché. Na koniec funkcie initScene() doplníme jeden riadok a máme guľu:

// vytvorenie gule
var sphere = BABYLON.Mesh.CreateSphere("sphere", 20.0, 10.0, scene);

Guľa je objekt odvodený od triedy Mesh vytvorený volaním metódy CreateSphere(). Parametre gule sú meno, počet segmentov (väčšie číslo znamená jemnejšiu segmentáciu), priemer a scéna. Keď teraz v našom webovom prehliadači spustíme súbor index.html, uvidíme vytvorenú guľu. Dokonca môžeme ňou pohybovať pomocou myši alebo klávesov so šípkami. Odprúčame vyskúšať!

Stred gule je štandardne umiestný v bode (0, 0, 0), ktorý by mal byť v strede okna prehliadača. Na obrázku však vyzerá guľa posunutá nižšie. Spôsobilo to nastavenie kamery. Prenecháme na čitateľa, aby si vyskúšal, ako vplývajú nastavenia kamery na zobrazenie útvaru.

Vyskúšame pridať ešte jeden útvar, napríklad uzol (“knot”).

// vytvorenie uzla
var knot = BABYLON.Mesh.CreateTorusKnot("knot", 2, 1, 128, 64, 2, 3, scene);

Tento útvar je zložitejší, má aj viac parametrov. Ich význam a tiež popis vytvárania ďalších základných útvarov môže čitateľ nájsť v oficiálnom tutoriáli v kapitole Discover Basic Elements (Objav základné prvky).

Pozícia, rotácia, škálovanie

Keď skúsime spustiť súbor index.html po pridaní druhého útvaru, bude obrázok rovnaký ako predtým. Na obrazovke vidno stále iba guľu. Je to preto, lebo oba útvary sa vytvorili na tom istom mieste a guľa prekryla uzol. Zmeníme preto pozíciu uzla, a to nastavením súradníc jeho stredu do bodu (10, 10, 10).

// nastavenie pozície uzla
knot.position.x = 10;
knot.position.y = 10;
knot.position.z = 10;

Pozíciu útvaru môžeme nastaviť buď vyššie uvedeným nastavením jednotlivých atribútov objektu position alebo naraz vytvorením nového objektu typu trojrozmerný vektor:

knot.position = new BABYLON.Vector3(10, 10, 10);

Niekedy je potrebné objekty preškálovať, t. j. zmeniť mierku zobrazenia. Je možné zvoliť pre každú súradnicovú os inú mierku. Skúsime teraz zmeniť mierku gule v smere každej osi na 1,5-násobok predchádzajúcej hodnoty, napríklad takto:

// preskalovanie gule
sphere.scaling = new BABYLON.Vector3(1.5, 1.5, 1.5);

Každý útvar možno podľa potreby natočiť o zvolený uhol podľa niektorej zo súradnícových osí. Nasledujúci príkaz natočí uzol o uhol 45 stupňov podľa osi x. Na vyjadrenie konštanty PI/4 použijeme objekt Math jazyka JavaScript.

// otocenie uzla podla osi x
knot.rotation.x = Math.PI/4;

Materiály, farby, textúry

Oba nami vytvorené objekty sú zatiaľ sivé. Je to preto, lebo majú nastavený predvolený materiál. Ako to zmeniť? V Babylon.js je materiál objekt triedy StandardMaterial, ktorej konštruktor má parametre názov a scéna. Našej guli môžeme priradiť nový materiál takto:

// vytvorenie noveho materialu
var sphereMaterial = new StandardMaterial("sphereMat", scene);
sphere.material = sphereMaterial;

Ak z iných dôvodov nepotrebujeme osobitnú premennú pre vytvorený materiál, dá sa to urobiť v jednom kroku. Urobíme to pre uzol.

knot.material = new BABYLON.StandardMaterial("knotMat", scene);

Po pridaní týchto riadkov na koniec funkcie initScene() však na objektoch nepozorujeme žiadnu zmenu. Prečo? Materiálom je možné nastavovať rôzne vlastnosti. Novovytvorené materiály majú stále nastavené predvolené vlastnosti. Skúsme zmeniť farbu objektov. Difúzna farba, čiže atribút diffuseColor objektu material, určuje vlastnú farbu materiálu. Pridajme riadky:

// nastavenie farby materialu
sphereMaterial.diffuseColor = new BABYLON.Color3.Red();
knot.material.diffuseColor = new BABYLON.Color3(0, 1, 0);

Podľa oficiálnej dokumentácie existujú v rámci Babylon.js statické metódy triedy Color3, pomocou ktorých môžeme nastaviť základné farby, napríklad Red(), Green(), Blue(), atď. Ak si chceme farby prispôsobiť, musíme použiť druhý spôsob, a to vytvorením objektu Color3 s parametrami (r, g, b). Výsledok vyzerá takto:

Okrem farby sa dá nastaviť aj textúra – štruktúra povrchu objektu. Textúra je zadaná obrázkom, ktorý musí byť vo vhodnom formáte, napríklad PNG, JPG, BMP, pričom musí byť daný formát podporovaný naším webovým prehliadačom. Príklady voľne prístupných textúr sú v repozitári Babylon.js. V našom príklade tiež použijeme textúry z tohoto zdroja. Obrázky, ktoré stiahneme zo zdroja, umiestnime do adresára assets.

Textúre možno nastaviť posun textúry na útvare pomocou atribútov uOffset a vOffset a opakovanie vzorky použitím atribútov uScale a vScale, pričom u znamená kladný smer osi x a v kladný smer osi y.

// pouzitie textur
sphere.material.diffuseTexture = new BABYLON.Texture("assets/rockn.png", scene);
sphereMaterial.diffuseTexture.uScale = 4.0;
sphereMaterial.diffuseTexture.vScale = 4.0;

knot.material.diffuseTexture = new BABYLON.Texture("assets/lavatile.jpg", scene);

Aha, a je tu zárodok našich planét a meteoritov!

Viac o materiáloch a textúrach sa môže čitateľ dozvedieť z oficiálneho tutoriálu z časti Materials (Materiály).

Vytvorme planéty a meteority

Všetko, čo sme sa doteraz naučili o vytváraní útvarov, využijeme pri vytvorení planét a meteoritov v našej hre. Teraz odstránime zo svojho súboru initScene.js všetok kód, ktorý sme vyrobili v rámci kapitoly Útvary na scénu! (vytváranie útvarov, nastavovanie ich vlastností, atď.).

Planéty a meteority budú mať v hre náhodnú veľkosť a náhodné súradnice polohy, meteority aj náhodnú rotáciu. Na generovanie náhodných čísel použijeme funkciu randomNumber(), ktorú umiestnime na koniec súboru initScene.js:

// funkcia na generovanie nahodnych cisel z intevalu (min, max)
var randomNumber = function (min, max) {
    if (min == max) {
        return (min);
    }
    var random = Math.random();
    return ((random * (max - min)) + min);
};

Za funkciu initScene() pridáme nasledujúcu časť kódu:

// funkcia na vytvorenie nahodnej planety pred kamerou

var createPlanet = function() {
    var minR = 30;
    var maxR = 80;

    if (planetMaterial == null) {
        planetMaterial = new BABYLON.StandardMaterial("planetMat", scene);
        planetMaterial.diffuseTexture = 
                         new BABYLON.Texture("assets/rockn.png", scene);
        planetMaterial.diffuseTexture.uScale = 4.0;
        planetMaterial.diffuseTexture.vScale = 4.0;
    }

    var planet = BABYLON.Mesh.CreateSphere("sphere", 20, 
                         randomNumber(minR, maxR), scene);
    planet.material = planetMaterial;

    var minZ = camera.position.z+500;
    var maxZ = camera.position.z+3000;
    var minY = camera.position.y-100;
    var maxY = camera.position.y+100;
    var minX = camera.position.x-200;
    var maxX = camera.position.x+200;

    planet.position.x = randomNumber(minX, maxX);
    planet.position.y = randomNumber(minY, maxY);
    planet.position.z = randomNumber(minZ, maxZ);
};

// funkcia na vytvorenie nahodneho meteoritu pred kamerou

var createMeteorite = function() {

    var minT = 4;
    var maxT = 8;

    if (meteoriteMaterial == null) {
        meteoriteMaterial = new BABYLON.StandardMaterial("meteoriteMat", scene);
        meteoriteMaterial.diffuseTexture = 
                            new BABYLON.Texture("assets/lavatile.jpg", scene);
    }

    var meteorite = BABYLON.Mesh.CreateTorusKnot("knot", 2, 
                            randomNumber(minT, maxT), 12, 64, 2, 3, scene);
    meteorite.material = meteoriteMaterial;

    var minZ = camera.position.z+500;
    var maxZ = camera.position.z+3000;
    var minY = camera.position.y-100;
    var maxY = camera.position.y+100;
    var minX = camera.position.x-200;
    var maxX = camera.position.x+200;

    meteorite.position.x = randomNumber(minX, maxX);
    meteorite.position.y = randomNumber(minY, maxY);
    meteorite.position.z = randomNumber(minZ, maxZ);

    meteorite.rotation.x = Math.PI*randomNumber(1,7)/4;
    meteorite.rotation.y = Math.PI*randomNumber(1,7)/4;
    meteorite.rotation.z = Math.PI*randomNumber(1,7)/4;
};

Treba upozorniť, že je potrebné deklarovať globálne premenné planetMaterial a meteoriteMaterial na začiatku súboru v časti deklarácií. Funkcie na vytvorenie planét a meteoritov budeme volať opakovane, ale materiály pre planéty a meteority vytvoríme len prvýkrát, lebo sú spoločné pre všetky planéty a pre všetky meteority.

Opakované volanie funkcií zabezpečíme pomocou funkcie setInterval(), ktorej parametrami sú názov funkcie a interval volania vyjadrený v milisekundách. Na koniec tela funkcie initScene() umiestnime nasledovné volania:

// vytvaranie meteoritov a planet v pravidelnych intervaloch
setInterval(createPlanet, 2000);
setInterval(createMeteorite, 1000);

Po spustení index.html vidíme na obrazovke postupné pribúdanie meteoritov a planét v diaľke pred kamerou. Každé dve sekundy pribudne jedna planéta a každú sekundu jeden meteorit. Scéna môže po niekoľkých sekundách vyzerať takto:

Vytvorme lietajúci tanier

V nasledujúcej časti ukážeme, ako sa v jazyku JavaScript definujú vlastné triedy. Výhodou je, že rozšírime triedu definovanú v rámci Babylon.js o špecifické atribúty a metódy, ktoré umožňujú špeciálne správanie objektov tejto triedy.

Vytvoríme triedu Ufo odvodenú od triedy Mesh. Každá trieda, podobne ako v iných objektovo orientovaných jazykoch, musí mať konštruktor, atribúty a metódy. Úlohou konštruktora je alokovať pamäť a inicializovať atribúty objektu. Najprv budeme definovať konštruktor a atribúty triedy. Posledné dva riadky zabezpečia dedenie od triedy Mesh.

// trieda Ufo odvodena od triedy BABYLON.Mesh

Ufo = function(name, scene, camera) {
    BABYLON.Mesh.call(this, name, scene);

    var torus = BABYLON.VertexData.CreateTorus({diameter: 4, 
                       thickness: 0.6,  tessellation: 12});
    var sphere = BABYLON.VertexData.CreateSphere({segments: 6, 
                       diameterX: 3.5, diameterY: 1.5, diameterZ: 3.5, slice: 3});
    sphere.merge(torus);
    sphere.applyToMesh(this, false);

    this.killed = false;
    this.position.x = 0;
    this.position.z = 0;
    this.position.y = 0;
    this.rotation.z = Math.PI/16;

    // atributy pohybu
    this.moveLeft = false;
    this.moveRight = false;
    this.moveUp = false;
    this.moveDown = false;
    this.speed = 3;
    this.fuel = 50;

    // odlozime si referenciu na kameru kvoli pohybu
    this.camera = camera;
};

Ufo.prototype = Object.create(BABYLON.Mesh.prototype);
Ufo.prototype.constructor = Ufo;

Túto časť kódu vložíme do nového súboru Ufo.js a súbor umiestnime do adresára js. Ešte je potrebné triedu Ufo inštanciovať a umiestniť vytvorený objekt na scénu. Preto do funkcie initScene() doplníme nasledovný riadok:

// vytvorenie ufo
ufo = new Ufo("ufo", scene, camera);

Nezabudnime vložiť do hlavičky súboru index.html riadok s cestou k novovytvorenému súboru:

<script src="js/Ufo.js"></script>

Použitie vytvorených atribútov popíšeme neskôr. Teraz spomeňme len význam atribútov killed a speed. Lietajúci tanier sa môže počas svojej cesty zraziť s planétou a vtedy dôjde k jeho zničeniu – atribút killed sa nastaví na hodnotu true. Atribút speed určuje rýchlosť pohybu lode.

VertexData

Pozrime sa bližšie na vytvorenie tvaru lietajúceho taniera. V kapitole Útvary na scénu! sme ukázali, ako ľahko sa vytvoria základné geometrické útvary. Teraz ukážeme vytvorenie útvarov volaním statických metód triedy VertexData. Útvary sú reprezentované množinou vrcholov – bodov v trojrozmernom priestore. Dva prepojené vrcholy vytvárajú hranu, tri navzájom prepojené vrcholy vytvárajú stenu v tvare trojuholníka. Z trojuholníkových stien je vytvorený mnohosten (zdroj — polygon mesh):

Každý vrchol nesie v sebe tri informácie:

  • pozíciu – súradnice vrchola v 3D priestore,
  • súradnicu textúry – určuje, ktorá časť textúry bude aplikovaná na tento vrchol,
  • normálový vektor – určuje orientáciu vrchola vzhľadom na svetelný zdroj.

Tieto údaje sú interne reprezentované pomocou štyroch polí, v ktorých sú uložené pozície, normály, súradnice textúr a trojice incidujúcich hrán tvoriacich trojuholníkové steny. Polia je možné modifikovať, čo dáva široké možnosti na vytváranie vlastných tvarov. V týchto poliach je však každý vrchol viackrát, podľa toho, ku koľkým stenám patrí, a preto pri úpravách musíme dbať na to, aby sme naraz upravili všetky vrcholy s tou istou pozíciou.

Pri konštruovaní lietajúceho taniera sme volaním statických metód CreateTorus() a CreateSphere() triedy VertexData vytvorili dva objekty torus a sphere. Všimnime si, že parametre sú zadané v tvare JSON, ktorý Babylon.js používa na popisovanie objektov. Podrobnosti môže čitateľ nájsť v dokumentácii Babylon.js v časti FileFormat Map.

Objekty vytvorené týmto spôsobom je možné ľahko zlučovať. Naše ufo je vytvorené pripojením objektu torus k objektu sphere jednoduchým príkazom:

sphere.merge(torus);

Výsledný tvar aplikujeme na objekt triedy Ufo:

sphere.applyToMesh(this, false); 

Po spustení uvidíme na scéne okrem planét aj lietajúci tanier, ale celá scéna je zatiaľ statická:

Doplňme palivo

Naša kozmická loď nemôže letieť bez paliva. Preto sme už pri vytváraní triedy Ufo definovali atribút fuel s počiatočnou hodnotou 50. Stav v nádrži chceme zobrazovať na obrazovke, preto do tela (body) súboru index.html pridáme nový oddiel:

<div id="fuelLabel">FUEL:</div>

a do súboru css/style.css doplníme jeho štýly:

#fuelLabel {
    position:absolute;
    top:20px;
    left : 20px;
    color:white;
    font-size: 2em;
}

Palivo počas letu ubúda. To zabezpečí metóda triedy Ufo decreaseFuel(), ktorú umiestnime do súboru Ufo.js. Táto metóda okrem samotného znižovania množstva paliva zašle udalosť fuelUpdated event handleru updateFuelLabel() pre obsluhu udalosti zníženie množstva paliva. Ďalej ošetruje aj rôzne prípady správania pre rôzne hodnoty paliva v nádrži.

// metoda pre znizenie mnozstva paliva
Ufo.prototype.decreaseFuel = function() {
    if (this.fuel <= 0)
        return;

    if (this.killed)
        this.fuel = 0;

    if (this.fuel > 0)
        this.fuel -= 1;

    if (this.fuel == 0)
        this.speed = 0;

    // zaslanie eventu pre vyvolanie prepisania
    // mnozstva paliva na obrazovke
    var e = new Event('fuelUpdated');
    e.fuel = ufo.fuel;
    window.dispatchEvent(e);
};

V ďalšom kroku zadefinujeme samotný event handler a namapujeme naň udalosť fuelUpdated. Na to bude slúžiť statická funkcia initLabelUpdate(), ktorá aktualizuje výpis na obrazovke pri zachytení udalosti fuelUpdated. Do súboru initScene.js pridáme nasledovný fragment kódu:

// staticka funkcia, ktora nastavi vypis na obrazovke 
// pri zachyteni eventu fuelUpdated
var initLabelUpdate = function() {

    var updateFuelLabel = function(evt) {
        document.getElementById("fuelLabel").innerHTML = "FUEL: " + evt.fuel;
    };

    // registracia udalosti
    BABYLON.Tools.RegisterTopRootEvents([{
        name:"fuelUpdated",
        handler : updateFuelLabel
    }]);
};

Ďalej do tohto súboru doplníme pomocnú funkciu updateLabel(), ktorá bude na objekte ufo volať metódu decreaseFuel().

var updateLabel = function() {
    ufo.decreaseFuel();
};

Túto funkciu budeme opakovane vyvolávať každú sekundu použitím funkcie setInterval(). Ešte treba inicializovať aktualizáciu výpisu. Na to slúži fukcia initLabelUpdate(). Do funkcie initScene() vložíme nasledovné riadky kódu:

// aktualizacia vypisu stavu paliva v pravidelnych intervaloch
setInterval(updateLabel, 1000);

// volanie funkcie na inicializaciu aktualizacie vypisu stavu paliva a pohybu
initLabelUpdate();

Treba ešte dodať, že ak je nádrž prázdna (fuel == 0), loď sa zastaví (speed = 0) a hra sa končí. Vtedy zastavíme aj generovanie ďalších planét a meteoritov. Do funkcií createPlanet() a createMeteorite() doplníme jednoduchú podmienku:

if (ufo.speed <= 0 || ufo.killed)
    return;

Letíme!

Náš lietajúci tanier je zatiaľ statický. Ako ho uvedieme do pohybu? Celkom jednoducho. Zmeníme doterajšiu hernú slučku. Pridáme posúvanie lode v kladnom smere osi z (dopredu) o jej rýchlosť pri každom vykreslení. Keďže kamera je umiestnená na lodi, rovnako budeme meniť aj jej pozíciu. Všetko sa bude diať za podmienky, že lietajúci tanier ešte nebol zničený.

Nová herná slučka bude vyzerať takto:

// spustenie hernej slucky
engine.runRenderLoop(function () {
    if (! ufo.killed) {
        ufo.position.z += ufo.speed;
        camera.position.z += ufo.speed;
    }
    scene.render();
});

Ako riadiť lietajúci tanier

Chceli by sme, aby hráč mohol riadiť lietajúci tanier. Pokúsime sa implementovať jeho ovládanie pomocou šípiek z klávesnice.

V triede Ufo už máme definované atribúty pohybu. Sú to atribúty moveLeft pre pohyb doľava, moveRight doprava, moveUp hore a moveDown dole. Ak má niektorý atribút hodnotu true, uskutoční sa pohyb lietajúceho taniera a zároveň kamery v danom smere. Prepínanie hodnôt atribútov vyvolá stlačenie alebo pustenie klávesu s príslušnou šípkou.
Do triedy Ufo doplníme dve metódy, ktoré nastavujú tieto atribúty. Metóda onKeyDown() zabezpečí, že pri stlačení klávesu so šípkou sa príslušný atribút nastaví na hodnotu true. Zároveň sa atribút pohybu v opačnom smere nastaví na false. Dvojhmaty, ktoré umožňujú pohyb lode šikmo, napríklad vľavo hore, sú prípustné. Metóda onKeyUp() nastaví pri pustení klávesu hodnoty všetkých týchto atribútov na false.

// osetrenie stlacenia klavesy pre zmenu smeru
Ufo.prototype.onKeyDown = function(keyCode) {

    if (keyCode == 37) {            // sipka dolava
        this.moveLeft = true;
        this.moveRight = false;
    } else if (keyCode == 39) {     // sipka doprava
        this.moveRight = true;
        this.moveLeft = false;
    }

    if (keyCode == 38) {            // sipka hore
        this.moveUp = true;
        this.moveDown = false;
    } else if (keyCode == 40) {     // sipka dole
        this.moveDown = true;
        this.moveUp = false;
    }

};

// osetrenie pustenia klavesy
Ufo.prototype.onKeyUp = function(keyCode) {
    ufo.moveRight = false;
    ufo.moveLeft = false;
    ufo.moveUp = false;
    ufo.moveDown = false;
};

Potom zadefinujeme statickú funkciu na nastavenie pohybu lode. Funkcia initMovement() vytvorí event handlery na ošetrenie vstupných udalostí stlačenie a pustenie klávesu a udalosti zaregistruje. Event handler vyvolá na objekte ufo metódu s rovnakým názvom. Do súboru initScene.js pridáme nasledujúcu časť kódu:

// staticka funkcia, ktora nastavi pohyb lode
var initMovement = function() {

    var onKeyDown = function(evt) {
        ufo.onKeyDown(evt.keyCode)
        };

    var onKeyUp = function(evt) {
        ufo.onKeyUp(evt.keyCode)
        };

    // registracia udalosti
    BABYLON.Tools.RegisterTopRootEvents([{
        name: "keydown",
        handler: onKeyDown
    }, {
        name: "keyup",
        handler: onKeyUp
    }]);
};

Ešte treba implementovať samotný pohyb lode, čiže zmenu súradníc x a y jej polohy podľa stlačených klávesov. Hýbať loďou je možné, kým má palivo. Zadefinujeme osobitnú metódu move() a umiestnime ju do triedy Ufo:

// metoda pre pohyb lode v nastavenom smere
Ufo.prototype.move = function() {

    // ak nema palivo, tak sa nepohybuje
    if (this.fuel <= 0)
        return;

    // ak mame nastaveny pohyb v danom smere, tak upravime prislusnu suradnicu
    // aj polohu kamery
    // pozor, moze byt nastaveny pohyb sucasne vo dvoch smeroch 
    // (napr. vpravo + hore)
    if (this.moveRight) {
        this.position.x += 1;
        this.camera.position.x += 1;
    }
    if (this.moveLeft) {
        this.position.x += -1;
        this.camera.position.x += -1;
    }
    if (this.moveUp) {
        this.position.y += 1;
        this.camera.position.y += 1;
    }
    if (this.moveDown) {
        this.position.y += -1;
        this.camera.position.y += -1;
    }

};

Teraz upravíme hernú slučku v súbore initScene.js. Doplníme do nej volanie metódy move(). Upravená herná slučka vyzerá nasledovne:

// spustenie hernej slucky
engine.runRenderLoop(function () {
    if (! ufo.killed) {
        ufo.move();

        ufo.position.z += ufo.speed;
        camera.position.z += ufo.speed;
    }
    scene.render();
});

Nakoniec pridáme na koniec funkcie initScene() nasledovný príkaz na inicializáciu pohybu:

initMovement();

Crash!

Lietanie na lietajúcom tanieri nie je také jednoduché, ako to zatiaľ vyzerá. Počas letu sa lietajúci tanier môže zraziť s planétou alebo s meteoritom. Ak sa zrazí s meteoritom, je to dobré, lebo rádioaktívny meteorit spôsobí doplnenie nádrže s palivom. Zrážka s planétou však vyvolá výbuch lietajúceho taniera a koniec hry. Ako naprogramovať takéto správanie? Našťastie Babylon.js má zabudovaný Action Manager, v ktorom sú už pripravené viaceré akcie a niektoré z nich bude výhodné práve v takomto prípade použiť.

Action Manager

Akcie podľa dokumentácie poskytujú jednoduchý spôsob, ako pridať objektom alebo scéne určité správanie. Akcie sú spúšťané triggrami, ktoré môžu byť takýchto druhov:

  • kliknutie alebo dotknutie sa objektu,
  • nastavenie kurzora na objekt,
  • prienik s iným objektom,
  • stisnutie alebo pustenie klávesu.

Nové triggre sa stále vyvíjajú. K triggru je možné pridať aj podmienku, ktorá vyhodnocuje hodnotu, predikát alebo stav. Trigger vyvolá akciu. Akcie by sa dali rozdeliť do troch skupín:

  • akcie, ktoré menia hodnoty premenných,
  • akcie, ktoré spúšťajú alebo zastavujú animácie,
  • používateľské akcie, ktoré si môže používateľ pripraviť sám.

Prehľad o triggroch, podmienkach a existujúcich akciách môže čitateľ získať z aktuálnej dokumentácie z časti How to use Actions (Ako používať akcie).

V našej hre chceme priradiť určité správanie lietajúcemu tanieru v situácii, keď sa zrazí s meteoritom alebo planétou. Preto použijeme OnIntersectionEnterTrigger. Ak sa zrazí s meteoritom, chceme nastaviť stav jeho paliva fuel na hodnotu 50, čo nám umožní SetValueAction. V prípade zrážky s planétou pomocou SwitchBooleanAction prestavíme hodnotu atribútu killed na opačnú (true).

Na koniec tela funkcie createMeteorite() doplníme takúto časť kódu:

// Action Manager
meteorite.actionManager = new BABYLON.ActionManager(scene);

// akcia pri kolizii meteoritu s lietajucim tanierom - nastavenie hodnoty paliva
var trigger = {trigger:BABYLON.ActionManager.OnIntersectionEnterTrigger, 
               parameter: ufo};
var sva = new BABYLON.SetValueAction(trigger, ufo, "fuel", 50);
meteorite.actionManager.registerAction(sva);

Pred použitím akcie musíme pripojiť ActionManager k meteoritu. Vytvoríme objekt trigger s dvomi parametrami – druhom triggra a objektom, s ktorým bude meteorit v kolízii (ufo). Potom vytvoríme novú SetValueAction s týmto triggrom. Druhým parametrom je atribút, ktorému akcia prestaví hodnotu a posledným nová hodnota atribútu. Nakoniec zaregistrujeme vytvorenú akciu.

Podobne na koniec tela funkcie createPlanet() vložíme časť kódu:

// Action Manager
planet.actionManager = new BABYLON.ActionManager(scene);

// akcia pri kolizii planety s lietajucim tanierom
// prestavenie hodnoty priznaku killed
var trigger = {trigger:BABYLON.ActionManager.OnIntersectionEnterTrigger, 
               parameter: ufo};
var sba = new BABYLON.SwitchBooleanAction(trigger, ufo, "killed");
planet.actionManager.registerAction(sba);

Čitateľ už iste sám pochopí význam jednotlivých príkazov.

Explózia

Keď sa lietajúci tanier zrazí s planétou, mal by vybuchnúť. Pri zrážke sa príznak killed vďaka SwitchBooleanAction nastaví na true, palivo vytečie a hra sa zastaví. Nevidíme však žiadny výbuch. Čitateľ je už natoľko zdatný, že môže sám skúsiť navrhnúť, ako nasimulovať explóziu.

Zatiaľ ponúkame jednoduché riešenie, v ktorom je výbuch vyrobený pomocou gule s textúrou distortion.png stiahnutou z repozitára Babylon.js. Obrázok s textúrou treba umiestniť do adresára assets. Na koniec súboru initScene.js pridáme nasledovnú časť kódu:

// funkcia na vytvorenie explozie
var createExplosion = function() {

    explosion = BABYLON.Mesh.CreateSphere("sphere", 6, 1, scene);
    explosion.material = new BABYLON.StandardMaterial("smoke", scene);
    explosion.material.diffuseTexture = 
                       new BABYLON.Texture("assets/distortion.png", scene);

    explosion.position.x = ufo.position.x;
    explosion.position.y = ufo.position.y;
    explosion.position.z = ufo.position.z;

    // znicenie lietajuceho taniera
    ufo.dispose();
};

// funkcia pre rozptylenie mraku po explozii
var expandExplosion = function() {
    var scalingVector = explosion.scaling;
    if (scalingVector.x > 10) {
        explosion.dispose();
        return;
    }
    scalingVector.x += 0.05;
    scalingVector.y += 0.05;
    scalingVector.z += 0.05;
    explosion.scaling = scalingVector;
    explosion.visibility -= 0.02;
};

Na záver pridáme riadenie explózie do hernej slučky. Jej nová verzia vyzerá takto:

// spustenie hernej slucky
engine.runRenderLoop(function () {
    if (! ufo.killed) {
        ufo.move();

        camera.position.z += ufo.speed;
        ufo.position.z += ufo.speed;
    }
    else {
        if (explosion == null)
            createExplosion();
        else
            expandExplosion();
    }

    scene.render();
});

Funkcia createExplosion() vytvorí na pozícii lietajúceho taniera guľu s textúrou dymu a zničí lietajúci tanier. Funkcia expandExplosion() zväčšuje dymovú guľu a zároveň znižuje jej viditeľnosť. Keď zväčšenie dosiahne 10-násobok pôvodnej veľkosti, guľa bude zničená. V hernej slučke sa za podmienky, že príznak killed je true, raz vyvolá funkcia createExplosion() a potom opakovane funkcia expandExplosion(). Nezabudnime deklarovať globálnu premennú explosion v časti deklarácií.

A predsa sa točí!

Ako všetci vieme, každá planéta rotuje okolo vlastnej osi. Skúsme aj my roztočiť naše planéty. Babylon.js poskytuje na to vhodný nástroj – animácie.

Animácie

Úlohou animácií (podľa dokumentácie) je simulovať pohyb objektov, presnejšie zmenu ich polohy alebo rotácie. Babylon.js ponúka jednoduché a zložitejšie animácie. V jednoduchej animácii je potrebné vytvoriť a naplniť pole animačných kľúčov a pre každý kľúč definovať, v akej situácii sa má objekt nachádzať. Zložitejšie animácie menia animačný kód počas behu programu. Podrobnejšie informácie o animáciách sú uvedené v dokumentácii Babylon.js v časti Animations (Animácie).

V našej hre vytvoríme jednoduchú animáciu, pomocou ktorej budú planéty rotovať okolo svojej osi rovnobežnej s osou y. Na koniec tela funkcie createPlanet() budeme postupne pridávať nižšie uvedené segmenty kódu:

// Animacia rotacie planety okolo osi y
var planetAnimation = 
    new BABYLON.Animation("Animation", "rotation.y", 60, 
                          BABYLON.Animation.ANIMATIONTYPE_FLOAT, 
                          BABYLON.Animation.ANIMATIONLOOPMODE_CYCLE);

Príkaz vytvorí animačný objekt. Jeho parametre sú:

  • meno animácie,
  • vlastnosť, ktorú chceme animáciou meniť,
  • rýchlosť animácie – počet snímkov za sekundu (“frames per second”),
  • typ hodnoty, ktorá sa bude modifikovať (FLOAT, VECTOR2, VECTOR3, QUATERNION, MATRIX, COLOR3),
  • typ správania po skončení animácie:
    • RELATIVE – použiť inkrement predchádzajúcej hodnoty,
    • CYCLE – opakovať s rovnakou iniciálnou hodnotou,
    • CONSTANT – ponechať konečnú hodnotu).
// deklaracia pola animacnych klucov
var keys = [];

// pri animacnom kluci 0 je hodnota rotacie 0
keys.push({
    frame: 0,
    value: 0
});

// pri animacnom kluci 60 je hodnota rotacie PI/2 
// (po 60 snimkoch sa planeta otoci o 90 stupnov)
keys.push({
    frame: 60,
    value: Math.PI/2
});

V tejto časti definujeme pole animačných kľúčov a naplníme ho hodnotami, ktoré definujú, o aký uhol na ktorom snímku sa má planéta otočiť. Pomocou poľa je možné definovať rôznu rýchlosť pre rôzne úseky medzi snímkami.

planetAnimation.setKeys(keys);
planet.animations.push(planetAnimation);
scene.beginAnimation(planet, 0, 60, true);

Prvý príkaz priradí pole kľúčov k animačnému objektu, druhý pripojí animáciu k premennej planet a posledný spustí animáciu pre planet od 0-tého po 60-ty snímok s opakovaním.

Takto sme to roztočili!

Stále tomu niečo chýba

Zdá sa, že hra už ako-tak funguje, ale stále to nevyzerá ako vo vesmíre. Čo tomu chýba? Každý by očakával, že v pozadí budú nejaké hviezdy a ďalšie vesmírne telesá. Aj na to má Babylon.js riešenie. Nech sa páči!

Skybox

Skybox (podľa dokumentácie) je vlastne kocka, ale nie celkom obyčajná. Má špeciálnu textúru a ďalšie špeciálne vlastnosti. Textúra pozostáva zo šiestich obrázkov. Vytvoríme pre ňu podadresár adresára assets s názvom skybox. V našej hre použijeme textúru nebula z repozitára Babylon.js. Stiahneme odtiaľ 6 obrázkov s názvami:

  • nebula_ns.jpg,
  • nebula_ny.jpg,
  • nebula_nz.jpg,
  • nebula_px.jpg,
  • nebula_py.jpg,
  • nebula_pz.jpg.

Do časti deklarácií pridáme globálnu premennú skybox. Do tela funkcie initScene() budeme vkladať nasledovné riadky kódu:

// vytvorenie skyboxu a nastavenie jeho vlastnosti
skybox = BABYLON.Mesh.CreateBox("skyBox", 100.0, scene);

Vytvoríme kocku skybox obvyklým spôsobom, ako sme sa naučili v kapitole Útvary na scénu! Teraz pridáme ďalšie vlastnosti, ako napríklad vypnutie vlastnosti back-face culling (vyradenie zadných stien zo zobrazovania), odstránenie odrazov a aplikujeme vybranú textúru.

var skyboxMaterial = new BABYLON.StandardMaterial("skyBox", scene);
skyboxMaterial.backFaceCulling = false;
skyboxMaterial.disableLighting = true;
skyboxMaterial.diffuseColor = new BABYLON.Color3(0, 0, 0);
skyboxMaterial.specularColor = new BABYLON.Color3(0, 0, 0);
skyboxMaterial.reflectionTexture = 
               new BABYLON.CubeTexture("assets/skybox/nebula", scene);
skyboxMaterial.reflectionTexture.coordinatesMode = BABYLON.Texture.SKYBOX_MODE;
skybox.material = skyboxMaterial;

Dôležité upozornenie! Aby sa skybox vykresľoval za všetkým ostatným, nastavíme:

skybox.renderingGroupId = 0;

Potom doplníme vyšsie renderingGroupId ostatným objektom, a to planétam a meteoritom v tele funkcií createPlanet() a createMeteorite() hodnotu 1, lietajúcemu tanieru pri jeho vytvorení vo funkcii initScene() hodnotu 2 a explózii vo funkcii createExplosion() hodnotu 3.

Nakoniec do hernej slučky pridáme príkaz, aby skybox nasledoval pohyb kamery. Nová herná slučka má tvar:

// spustenie hernej slucky
engine.runRenderLoop(function () {
    if (! ufo.killed) {
        ufo.move();

        camera.position.z += ufo.speed;
        ufo.position.z += ufo.speed;
        skybox.position = camera.position;
    }
    else {
        if (explosion == null)
            createExplosion();
        else
            expandExplosion();
    }

    scene.render();
});

Ďalšie informácie o použití skyboxu sa čitateľ môže dozvedieť z oficiálnej dokumentácie z časti Environment (Prostredie) – Skybox.

Hmla

Aby sme dosiahli efekt, že planéty a meteority vznikajú v nekonečne, trošku tú diaľku zahmlíme. Do funkcie initScene() pridáme dva riadky. Význam parametrov a ďalšie možnosti využitia vysvetľuje dokumentácia v časti Environment (Prostredie) – Fog.

// nastavenie hmly
scene.fogMode = BABYLON.Scene.FOGMODE_EXP2;
scene.fogDensity = 0.002;

Preč so zbytočnými objektmi

Počas letu lietajúceho taniera vygenerujeme veľa planét a meteoritov. Aj keď odletia z nášho dohľadu, stále sú tam. Aby sme zbytočné objekty odstránili, použijeme malý trik. Zničíme objekty, ktoré sú za kamerou.

Ako globálnu premennú deklarujeme pole:

// deklaracia pola objektov, ktore sa maju znicit
SPACE_OBJECTS = [];

Pri vytvorení novej planéty, resp. meteoritu, vo funkcii createPlanet(), resp. createMeteorite() vložíme objekt do vytvoreného poľa:

// vlozenie planety do pola, ktore sa pouzije na nicenie nepotrebnych objektov
SPACE_OBJECTS.push(planet);

resp.

// vlozenie meteoritu do pola, ktore sa pouzije na nicenie nepotrebnych objektov
SPACE_OBJECTS.push(meteorite);

Vytvoríme funkciu na ničenie tých objektov poľa, ktoré sú za kamerou, teda súradnica z ich pozície je menšia ako súradnica z kamery (v danom momente). Pri zničení objektu zároveň skrátime dĺžku poľa.

// funkcia na nicenie planet a meteoritov za kamerou
var destroyObjects = function() {
    for (var i = 0; i < SPACE_OBJECTS.length; i++) {
        if (SPACE_OBJECTS[i].position.z < camera.position.z) {
            var o = SPACE_OBJECTS[i];
            o.dispose();
            SPACE_OBJECTS.splice(i,1);
            i--;
        }
    }
};

Túto časť kódu pridáme na koniec súboru initScene.js. Funkciu voláme napríklad každých 10 sekúnd. Volanie pridáme do tela funkcie initScene().

// znicenie nepotrebnych objektov v pravidelnych intervaloch
setInterval(destroyObjects, 10000);

A je to!

Prvá verzia hry je hotová. Zahrajme sa!

Úplné zdrojové texty sú prístupné v systéme GitLab Katedry počítačov a informatiky.

V tomto tutoriáli boli použité informácie z tutoriálov a ďalšie materiály z oficiálnej dokumentácie Babylon.js. Inšpiráciou boli aj tutoriály Juliana Chenarda, snažili sme sa však o vlastný prístup, rozšírenie popisovanej funkcionality, resp. čistejší návrh z pohľadu objektového programovania. Video ukážky boli vyrobené pomocou produktu Camtasia 9. Článok je pomerne rozsiahly, no aj tak poskytuje len základné informácie o možnostiach produktu Babylon.js. Ak niekoho téma zaujala, môže využiť spomenuté zdroje ako odrazový mostík pre ďalšie štúdium.

Pridaj komentár

Vaša e-mailová adresa nebude zverejnená. Vyžadované polia sú označené *

Táto webová stránka používa Akismet na redukciu spamu. Získajte viac informácií o tom, ako sú vaše údaje z komentárov spracovávané.