1. díl - Vytvoř si vlastní webovou hru

JavaScript 3D webová hra Vytvoř si vlastní webovou hru

Unicorn College ONEbit hosting Tento obsah je dostupný zdarma v rámci projektu IT lidem. Vydávání, hosting a aktualizace umožňují jeho sponzoři.

Vítej u prvního dílu seriálu, ve kterém ti ukážu, jak vyrobit vlastní 3D webovou hru. V tomto seriálu bych rád začal jednoduchou 3D scénou, kterou budu postupně rozvíjet do plnohodnotné 3D multiplayer realtime webové hry. Mám promyšlených několik článků dopředu a dál nechávám vše otevřené. Pokud se chceš připojit, můžeš přispívat na GitHubu kde budeme vždy o krok napřed před tímto tutoriálem. Nebo můžeš napsat či přijít na Povídací sraz ITnetwork a říct, co bys rád zlepšil.

Vše budu vyvíjet na GitHubu a sem budu vždy psát poslední krok formou tutoriálu.

Až bude mít hra serverovou část umístím ji online na samostatnou doménu.

Webová hra

Hra na webu vs. webová hra

Hned na začátku bych rád vysvětlil, proč dělám hru v JavaScriptu a ne v herním enginu jako např. Unity, kterou bych následně vyexportoval na web či dal na stažení na svůj web a na Steam. Rád bych docílil toho, aby hra kterou vytvořím, měla všechny vlastnosti, díky kterým jsou webové aplikace tak skvělé:

  • Nechci žádné zdlouhavé načítání. Chci, aby po zadání adresy hra prostě běžela.
  • Chci mít možnost hru spustit na mnoha záložkách prohlížeče, tak aby se jednotlivé instance vzájemně nerozbily.
  • Chci plně využít URL adresu. Tzn. když ve hře udělám nějaký postup, chci aby se mi promítl do URL. Pokud toto URL někomu pošlu, chci aby byl ve stejném stavu jako já.
  • Chci, aby mi fungovala prohlížečová tlačítka zpět a vpřed.
  • Chci, aby vyhledávače uměli moji hru projít a zaindexovat.
  • Chci, abych mohl místa a části mé hry sdílet na sociáních sítích s plně fungujícím nadpisem, popiskem a náhledem.

Chtěl bych se tím zároveň odlišit od her na webu, které sám definuju takto:

  • Je umístěna na jedné HTML stránce, která obvykle slouží pouze jako "obal" na hru, kterou obvykle obalí reklamou + nějakým stručným návodem a ošklivým pozadím.
  • Má jednu URL adresu.
  • Pokud stránku obnovím, mám po rozehrané hře. To samé platí pokud omylem kliknu na nějaký odkaz či tlačítko zpět.
  • Obvykle není responzivní.

Vývoj

Hru budu vytvářet ve WebGL frameworku BabylonJS, na držení stavu hry zvolím Redux+Immutable.js, na tvorbu UI využiji React, na mnoho různých věcí Lodash a jistě další frameworky a nástroje. Prvních několik článků napíšu v ES6, aby vše fungovalo přímo v nových prohlížečích bez transpilace, potom přejdu na TypeScript a využiji Gulp a Webpack.

Pokud ti bude připadat, že se dá něco udělat lépe, určitě mi napiš! Mám zkušenosti s vývojem webů, her, her na webu i webových her, ale jistě se v mnohých věcech můžu mýlit, či používat horší postup, než bys uměl ty. Sám bych rád zužitkoval mnohaleté zkušenosti s vývojem hry Towns a vývojem galerií na webu a vytvořil něco nového zajímavého.

Na konci dnešního článku budeš vědět, jak vytvořit editovatelnou a interaktivní 3D scénu pomocí WebGL frameworku BabylonJS.

Vytvoření první jednoduché 3D scény

Nejdříve vytvořím čistý index.html a přidám do něj knihovny BabylonJS a polyfill HandJS, který slouží ke sjednocení událostí myši a dotykových zařízení.

<script src="https://cdnjs.cloudflare.com/ajax/libs/babylonjs/2.5.0/babylon.max.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/handjs/1.3.11/hand.js"></script>

Potom do těla html stránky přidám canvas s id "scene".

<canvas id="scene"></canvas>

Canvas roztáhnu na plnou velikost stránky.

#scene {
  position: fixed;
  top: 0;
  left: 0;
  width: 100vw;
  height: 100vh;
  touch-action: none;
}

Poté definuji funkci, která vytvoří základní scénu, ta může být v samostatném .js souboru nebo přímo v index.html.

function createScene(canvas, engine) {
    //Vytvoření scény a nastavení základní barvy na bílou
    const scene = new BABYLON.Scene(engine);
    scene.clearColor = new BABYLON.Color3(1,1,1);

    //Vytvořím kameru, nastavím ji fov(field of view) a pomocí metody attachControl nastavím ať kamera reaguje na události.
    const camera = new BABYLON.ArcRotateCamera("Camera",Math.PI/4, Math.PI/4, 10, BABYLON.Vector3.Zero(), scene);
    camera.fov = 1.2;
    camera.attachControl(canvas, true);

    //Vytvořím osvětlení scény
    const light = new BABYLON.HemisphericLight("hemi", new BABYLON.Vector3(0, 1, 1/2), scene);

    //Vytvořím první mesh ve scéně - krychly o rozměrech 1x1x1. Mesh je 3D babylon objekt ve scéně, aby však nedocházelo ke zmatkům, budu je nazývat prostě mesh.
    const box = BABYLON.Mesh.CreateBox("box", 1, scene);

    return scene;
}

Zatím jsem pouze napsal funkci, která mi 3D scénu vytvoří. Nyní tuto funkci použiji: Kód který píšu musí být spuštěn až po vytvoření canvasu - tzn. script musí být umístěn pod canvasem nebo to celé musí být obaleno událostí onload.

var canvas = document.getElementById("scene");//Najdu canvas v DOMu.
var engine = new BABYLON.Engine(canvas, true);//Vytvořím Babylon engine.
var scene = createScene(canvas, engine);//Pomocí mnou definované funce vytvořím scénu.

Ještě je potřeba rozhýbat scénu.

engine.runRenderLoop(function() {
  scene.render();
});

Teď už máme vytvořenou scénu s krychlí, která plně funguje. Ještě je potřeba zajistit, aby se při změně velikosti okna scéna přizpůsobovala.

window.addEventListener("resize", function() {
  engine.resize();
});

Události

Ve scéně napsané výše si můžeme s 3D krychlí otáčet a zoomovat (díky metodě attachControl na kameře), ale to je vše. V další části článku do scény přidám větší interaktivitu.

Do funkce createScene přidám na konec posluchač na událost pointerup na canvasu. Ta se zavolá jak při klepnutí myši, tak při dotyku na obrazovku (a na starších prohlížečích funguje právě díky polyfillu HandJS, který jsem přidával hned na začátku článku.)

Při zavolání funkce onPointerUp se krychle posune o 1 na ose y.

function onPointerUp(event) {
    box.position.y++;
}

canvas.addEventListener("pointerup", onPointerUp, false);

Zatím ukázka funguje tak, že se při klepnutí kamkoliv na canvas posune krychle o 1 nahoru. V následující úpravě to udělám tak, aby se krychle posunula pouze pokud klepnu na ni.

function onPointerUp(event) {
    //Zjistím informace o bodu, na který jsem klepl.
    const pickInfo = scene.pick(scene.pointerX, scene.pointerY);
    //Pomocí klíče hit zjistím, zda jsem klepl na nějaký mesh ve scéně nebo do prázdna.
    if (pickInfo.hit) {
        //Zjistím konkrétní mesh, na který jsem klepl a ten posunu.
        const currentMesh = pickInfo.pickedMesh;
        currentMesh.position.y++;
    }
}

Pokud by nyní bylo ve scéně více krychlí, posunula by se vždy ta, na kterou jsem klikl.

Krychli však nemusím posouvat pouze jedním směrem, mohu je posunout tím směrem, na který jsem na její povrch klikl. To docílím pomocí hodnoty pickInfo.picked­Point.

function onPointerUp(event) {
    const pickInfo = scene.pick(scene.pointerX, scene.pointerY);
    if (pickInfo.hit) {
        const currentMesh = pickInfo.pickedMesh;
        currentMesh.position = pickInfo.pickedPoint.clone();//Je bezpečnější pozici naklonovat, než předávat tu samou instanci pozice.
    }
}

Vytváření nových krychlí

Velmi jednoduchou úpravou mohu na nové pozici vytvářet nové krychle.

function onPointerUp(event) {
    const pickInfo = scene.pick(scene.pointerX, scene.pointerY);
    if (pickInfo.hit) {
        const currentMesh = pickInfo.pickedMesh;
        const newBox = currentMesh.clone();
        newBox.position = pickInfo.pickedPoint.clone();
    }
}

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 hejny.github.io/web-game. V dalším díle ukáži, jak mohu krychle zarovnat do mřížky, jak krychle mazat. Napíši něco k materiálům a jak díky tomu mohu provádět hoover efekt podobný css.


 

Stáhnout

Staženo 76x (2.23 kB)
Aplikace je včetně zdrojových kódů v jazyce JavaScript

 

 

Článek pro vás napsal Pavol Hejný
Avatar
Jak se ti líbí článek?
4 hlasů
Autor se věnuje vývoji mnoha www aplikací - https://www.pavolhejny.com/
Miniatura
Všechny články v sekci
Vytvoř si vlastní 3D webovou hru
Miniatura
Následující článek
Vylepšování základní scény
Aktivity (14)

 

 

Komentáře

Avatar
Honza Bittner
Šupák
Avatar
Honza Bittner:7. června 22:26

To bude super série. Jen to tvé odsazování kódu náhodným počtem prázdných řádků mě asi zabije. :D

Odpovědět 7. června 22:26
Milovník Dartu. Student FIT ČVUT. Sleduj mě na https://twitter.com/tenhobi a zeptat se mě na cokoli můžeš na https://...
Avatar
Pavol Hejný
Autoredaktor
Avatar
Odpovídá na Honza Bittner
Pavol Hejný:8. června 12:02

Už mně to říká tenhle týden několikátý člověk, zapracuji na tom... A dík za pochvalu, snad naplním tvé očekávání :)

 
Odpovědět  +1 8. června 12:02
Avatar
Honza Bittner
Šupák
Avatar
Odpovídá na Pavol Hejný
Honza Bittner:8. června 12:25

Jestli používáš nějaké chytré IDE, třeba od JetBrains, tak to umí zredukovat samo pomocí formátování kódu, tuším CTRL + SHIFT + L. :P

Odpovědět  +1 8. června 12:25
Milovník Dartu. Student FIT ČVUT. Sleduj mě na https://twitter.com/tenhobi a zeptat se mě na cokoli můžeš na https://...
Avatar
Honza Bittner
Šupák
Avatar
Odpovídá na Pavol Hejný
Honza Bittner:9. června 0:11
  • dost pomáhá i editorconfig. :-)
Odpovědět  +1 9. června 0:11
Milovník Dartu. Student FIT ČVUT. Sleduj mě na https://twitter.com/tenhobi a zeptat se mě na cokoli můžeš na https://...
Avatar
patrik.valkovic
Šéfredaktor
Avatar
Odpovídá na Pavol Hejný
patrik.valkovic:9. června 0:25

Popřípadě by šel použít nějaký Linter, ten toho pohlídá ještě víc a například WebStorm ho umí automaticky integrovat.

Odpovědět  +2 9. června 0:25
Nikdy neumíme dost na to, abychom se nemohli něco nového naučit.
Avatar
Adam Danek
Člen
Avatar
Adam Danek:26. června 21:11

Jak má být ten začátek? když napíšu #scene napíše mi to, že # je neplatný znak

 
Odpovědět 26. června 21:11
Avatar
Pavol Hejný
Autoredaktor
Avatar
Odpovídá na Adam Danek
Pavol Hejný:26. června 23:07

Kam píšeš #scene, to je totiž pouze v css? Z toho problému, co píšeš mám pocit, že přímo do js? Poslal bys mi sem prosím screenshot nebo zdrojový kód, abych ti mohl poradit?

 
Odpovědět 26. června 23:07
Avatar
Michal Rosival:28. července 14:55

Mohol by si mi prosím ťa poradiť prečo mám error 404 not found na riadku:
<script type="text/ja­vascript" src="https://­www.babylonjs­.com/BabylonJS"></scrip­t>

 
Odpovědět 28. července 14:55
Avatar
Pavol Hejný
Autoredaktor
Avatar
Odpovídá na Michal Rosival
Pavol Hejný:30. července 1:10

Díky za upozornění na chybu. Babylon změnil umístění svých zdrojáků, můžeš použít tohle, už je to opravené i ve článku:

<script src="https://cdnjs.cloudflare.com/ajax/libs/babylonjs/2.5.0/babylon.max.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/handjs/1.3.11/hand.js"></script>
 
Odpovědět 30. července 1:10
Děláme co je v našich silách, aby byly zdejší diskuze co nejkvalitnější. Proto do nich také mohou přispívat pouze registrovaní členové. Pro zapojení do diskuze se přihlas. Pokud ještě nemáš účet, zaregistruj se, je to zdarma.

Zobrazeno 9 zpráv z 9.