2. diel - Vylepšovanie základnej scény
V minulom diele som ukázal, ako vytvoriť jednoduchú scénu, kam sa dajú pridávať kocôčky pomocou klikanie myšou. V tomto diele napíšem ako tieto kocky zarovnáme do mriežky, ako je z tejto scény môžem mazať pomocou pravého tlačidla myši, niečo o materiáloch a ako docieliť hover efektu.
Zarovnanie do mriežky
Ak chcem, aby sa mi nová kocka zarovnala do mriežky, nemôžem používať priamo hodnotu pickInfo.pickedPoint (viď. Predchádzajúci článok), ale musím to napísať málinko zložitejšie.
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 taleranci 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]++; } }); } }
Mazanie kociek
Do funkcie onPointerUp pridáme swich, aby sme určili, či klikáme ľavým či pravým tlačidlom.
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 valmi jednoduše zavoláním metody dispose. break; } } }
Ak však kľučkám na canvas pravým tlačidlom, vyskočí mi kontextové menu a to nechcem. Pomocou udalosti ContextMenu a metódy preventDefault tomu zabránim.
function onContextMenu(event){event.preventDefault()} canvas.addEventListener("contextmenu",onContextMenu, false);
Materiály
Všetky vytvorené kocky zatiaľ dostávali defaultný sivý povrch. Aby sme mohli docieliť iné, než základné šedej, potrebujeme použiť materiály. Materiály určujú vzhľad jednotlivých mesh. Každý materiál sa skladá zo 4 častí:
- Ambient - Okolité konštantné osvetlenie, čo osvetľuje predmet rovnomerne bez ohľadu na smer osvetlenia.
- Diffuse - Svetlo rozptýlené do všetkých strán. Vďaka tejto zložke je na predmete vytvorený "3D efekt".
- Specular - Svetlo odrážajúce sa prevažne v jednom smere, čo tvorí odlesk.
- Emissive - Svetlo vyžarované z meshe, hodí sa napr. Pre vytvorenie monitora alebo kina v scéne.
Ak chceš vedieť viac prečítaj si niečo o Phongově osvetľovacím modeli.
Každú z tehty 4 zložiek môžeme naplniť farbou alebo textúrou. Existujú aj veľmi pokročilých textúry, pomocou ktorých môžeme vytvoriť efekt zrkadlá, vodné kvapku a miesto statického obrázku zobrazovať video či na textúru kresliť, ako na canvas.
V tejto ukážke však budeme používať iba jednofarebné materiály.
Vo funkcii createScene (pred miesto, kde vytváram prvý kocku) vytvoríme dva materiály - jeden pre normálnu kocku a jeden pre kocku na ktorej 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 rovno nastavíme materialNormal prvý kocku.
const box = BABYLON.Mesh.CreateBox("box", 1, scene); box.material = materialNormal;
Poznámka: Typická vec pre BabylonJS je, že každá vec, ktorá sa viaže s konkrétnou inštanciou scény Camera, Mesh, Light, Material a mnoho ďalších má názov ako prvý parameter v konstruktoru a ako posledný parameter má scénu.
Hoover efekt
Tam, kde sa nachádza poslucháč udalosti pointerup, pridám navyše poslucháč udalosti 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);
Rozrobenú hru si môžeš stiahnuť pod článkom, alebo ísť do Git repozitára, kde nájdeš najnovšiu verziu zdrojových kódov. Alebo si ju rovno môžeš vyskúšať na webappgames.github.io/web-game. V ďalšom diele ukážem, ako môžem držať stav celej aplikácie lepšie, než priamo v scéne.
Mal si s čímkoľvek problém? Stiahni si vzorovú aplikáciu nižšie a porovnaj ju so svojím projektom, chybu tak ľahko nájdeš.
Stiahnuť
Stiahnutím nasledujúceho súboru súhlasíš s licenčnými podmienkami
Stiahnuté 83x (4.07 kB)
Aplikácia je vrátane zdrojových kódov v jazyku JavaScript