Lekce 2 - Vylepšování základní scény
V minulém díle, Vytvoř si vlastní webovou hru, jsem ukázal, jak vytvořit jednoduchou scénu, kam se dají přidávat krychličky pomocí klikání myší.
V tomto díle napíšu jak krychle zarovnám do mřížky, jak je z této scény mohu mazat pomocí pravého tlačítka myši, něco o materiálech a jak docílit hover efektu.

Zarovnání do mřížky
Pokud chci, aby se mi nová krychle zarovnala do mřížky, nemůžu používat přímo hodnotu pickInfo.pickedPoint(viz. předchozí článek), ale musím to napsat malinko složitěji.
function onPointerUp(event) { const pickInfo = scene.pick(scene.pointerX, scene.pointerY); if (pickInfo.hit) { const currentMesh = pickInfo.pickedMesh; const newBox = currentMesh.clone(); newBox.position = currentMesh.position.clone();// vytvářím novou krychli na stejné pozici. const diff = currentMesh.position.subtract(pickInfo.pickedPoint);// Beru rozdíl mezi středem krychle, na kterou jsem klikl a bodem na jejím povrchu, na který jsem klikl. // Pro každou dimenzi zjišťuji, zda v ní došlo k posunu právě o 0.5. Nepoužívám přesně 0.5, ale dávám tam toleranci 0.001, je to kvůli častému problému, kdy mám v proměnné místo 5 0.499999... ['x', 'y', 'z'].forEach((dimension) => { if (diff[dimension] >= 0.5 - 0.001) { newBox.position[dimension]--; } else if (diff[dimension] <= -0.5 + 0.001) { newBox.position[dimension]++; } }); } }
Mazání krychlí
Do funkce onPointerUp()
přidáme switch, abychom určili, zda
klikáme levým či pravým tlačítkem:
function onPointerUp(event) { const pickInfo = scene.pick(scene.pointerX, scene.pointerY); if (pickInfo.hit) { const currentMesh = pickInfo.pickedMesh; switch (event.button) { case 0: const newBox = BABYLON.Mesh.CreateBox("box", 1, scene); newBox.position = currentMesh.position.clone(); const diff = currentMesh.position.subtract(pickInfo.pickedPoint); ['x', 'y', 'z'].forEach((dimension) => { if (diff[dimension] >= 0.5 - 0.001) { newBox.position[dimension]--; }else if (diff[dimension] <= -0.5 + 0.001) { newBox.position[dimension]++; } }); break; case 2: currentMesh.dispose();// Každý mesh můžeme smazat velmi jednoduše zavoláním metody dispose. break; } } }
Pokud však klikám na canvas pravým tlačítkem, vyskočí mi kontextové
menu a to nechci. Pomocí události contextmenu a metody
preventDefault()
tomu zabráním:
function onContextMenu(event){event.preventDefault()} canvas.addEventListener("contextmenu",onContextMenu, false);
Materiály
Všechny vytvořené krychle zatím dostávali defaultní šedý povrch. Abychom mohli docílit jiné, než základní šedé, potřebujeme použít materiály. Materiály určují vzhled jednotlivých meshů. Každý materiál se skládá ze 4 složek:
- Ambient - Okolní konstantní osvětlení, co osvětluje předmět rovnoměrně bez ohledu na směr osvětlení.
- Diffuse - Světlo rozptýlené do všech stran. Díky této složce je na předmětu vytvořený "3D efekt".
- Specular - Světlo odrážející se převážně v jednom směru, co tvoří odlesk.
- Emissive - Světlo vyzařované z meshe, hodí se např. pro vytvoření monitoru nebo kina ve scéně.
Pokud chceš vědět více přečti si něco o Phongově osvětlovacím modelu .
Každou z těhto 4 složek můžeme naplnit barvou nebo texturou. Existují i velmi pokročilé textury, pomocí kterých můžeme vytvořit efekt zrcadla, vodní kapku a místo statického obrázku zobrazovat video či na texturu kreslit, jako na canvas.
V této ukázce však budeme používat pouze jednobarevné materiály.
Ve funkci createScene()
(před místo, kde vytvářím první
krychli) vytvoříme dva materiály - jeden pro normální krychli a jeden pro
krychli na které bude :hover
efekt.
const materialNormal = new BABYLON.StandardMaterial("material-normal", scene); materialNormal.diffuseColor = new BABYLON.Color3(0.4, 0.4, 0.4);// Také bych mohl vyrobit barvu z hexadecimálního zápisu BABYLON.Color3.FromHexString("#666666"); const materialHover = new BABYLON.StandardMaterial("material-hover", scene); materialHover.diffuseColor = new BABYLON.Color3(0.4, 1, 0.4);
A rovnou nastavíme materialNormal první krychli:
const box = BABYLON.Mesh.CreateBox("box", 1, scene); box.material = materialNormal;
Poznámka: Typická věc pro BabylonJS je, že každá věc, která se váže s konkrétní instancí scény Camera, Mesh, Light, Material a mnoho dalších má název jako první parametr v konstruktoru a jako poslední parametr má scénu.
Hover efekt
Tam, kde se nachází posluchač události pointerup, přidám navíc posluchač události pointermove.
let lastMesh = null; function onPointerMove(event) { if (lastMesh) { lastMesh.material = materialNormal; } const pickInfo = scene.pick(scene.pointerX, scene.pointerY); if (pickInfo.hit) { const currentMesh = pickInfo.pickedMesh; currentMesh.material = materialHover; lastMesh = currentMesh; } else { lastMesh = null; } } canvas.addEventListener("pointermove", onPointerMove, false);
Rozdělanou hru si můžeš stáhnout pod článkem, nebo jít do Git repozitáře, kde najdeš nejnovější verzi zdrojových kódů. Nebo si ji rovnou můžeš vyzkoušet na webappgames.github.io/web-game.
V dalším díle, Stav hry, ukáži, jak můžu držet stav celé aplikace.
Měl jsi s čímkoli problém? Stáhni si vzorovou aplikaci níže a porovnej ji se svým projektem, chybu tak snadno najdeš.
Stáhnout
Stažením následujícího souboru souhlasíš s licenčními podmínkami
Staženo 83x (4.07 kB)
Aplikace je včetně zdrojových kódů v jazyce JavaScript