Board game
Nejprve si forkněte z githubu repozitář s výchozím bodem k tomuto projektu.
Popis programu
Základem celé aplikace je dvourozměrné pole game_board
(10x10). K jednomu prvku pole přistoupíme pomocí dvou hranatých závorek. Tzn. například:
game_board[1][0] = 10
uloží na první řádek a nultý sloupec hodnotu 10. Jednotlivé políčka v game_board
jsou nastavená na hodnotu nula nebo jedna. Hodnota jedna má vyjadřovat, že se na dané pozici nachází překážka.
Dále se v programu nachází proměnné x
a y
, které uchovávají pozici hráče. Hráč je ovládán šipkami a posun v poli je implementován ve funkci moveCircle
.
Vytvoření herní mapy
Potřebujeme projít každý prvkek v dvourrozměrném poli, které reprezentuje herní mapu. Jelikož známe velikost tohoto pole, můžeme použít cyklus for
.
for (let index = 0; index < game_board.length; index++) {
// něco udělej
}
Jak můžete vidět, udáváme cyklu for
při jeho vytváření tři údaje.
let index = 0
- vytvoříme si novou proměnnou, do které ukládáme průběžný stav cyklu.index < game_board.length
- podmínka za jaké má cyklus pokračovatindex++
- na konci každého cyklu zvýší hodnotuindex
o jedna (index = index + 1)
Ukažme si to na příkladu, chceme 10x vypsat “ahoj”.
for (let index = 0; index < 10; index++) {
console.log("ahoj");
}
Nyní zkusíme tento cyklus použít k vypsání prvků v poli. Nejdříve si vypíšeme pouze jednotlivé řádky.
for (let radek = 0; radek < game_board.length; radek++) {
console.log(game_board[radek]);
}
Cheme ale vypsat každý prvek zvlášť. Použijeme tedy druhý for
pro vypsání prvků z každého řádku.
for (let radek = 0; radek < game_board.length; radek++) {
for (let sloupec = 0; sloupec < game_board.length; sloupec++) {
console.log(game_board[radek][sloupec]);
}
}
Herní mapu reprezentujeme, jako HTML tabulku. Stejně jako naše 2d pole je tabulka složena z řádků a sloupců. Konkrétní prvek v poli nazýváme “buňka”.
const radek = document.createElement("tr");
const bunka = document.createElement("td"); // skládáním za sebe tvoříme sloupce
HTML elementům můžeme přidávat vlastnosti. Třídu můžeme přidat pomocí metody classList.add()
.
square.classList.add("square");
Vytvoření elementu však nestačí pro jeho zobrazení. Na stránku ho přidáme pomocí metody appendChild()
bunka.appendChild(square);
Herní mapa je čtvercová => počet řádků je roven počtu sloupců. S těmito znalostmi jsme nyní schopni vytvořit herní mapu.
for (let radek = 0; radek < game_board.length; radek++) {
const radek_tabulky = document.createElement("tr"); // Vytvoříme nový řádek tabulky
for (let sloupec = 0; sloupec < game_board.length; sloupec++) {
const bunka_tabulky = document.createElement("td"); // Vytvoříme novou buňku tabulky
radek_tabulky.appendChild(bunka_tabulky); // Přidáme novou buňku do řádku tabulky
if (game_board[radek][sloupec] == 1) {
// Pokud se na této pozici nachází překážka
const square = document.createElement("div"); // Vytvoříme element div, který slouží jako zábrana
square.classList.add("square"); // Přidáme divu třídu pro pozdější nastavení jeho vlastností
bunka_tabulky.appendChild(square); // Přidáme div do buňky tabulky
}
}
board.appendChild(radek_tabulky); // přidáme celý řádek do tabulky
}
Úkoly
U této verze zkuste následující úkoly:
- Ošetřete v metodě
moveCircle
pohyb hráče tak, aby nemohl vstoupit na pole s překážkou (tzn.game_board
je na dané pozici nastaven na jedna) - Změňte obrázek překážky z modrého čtverce na nějaký obrázek (např. stěna)
- Změňte obrázek hráče z červeného kruhu na nějaký obrázek (např. auto, osoba zvrchu)
- Přidejte do
game_board
novou hodnotu 2, která bude reprezentovat nějakou odměnu, kterou chceme sebrat. UpravtecreateBoard()
funkci, aby se odměny zobrazovaly v HTML. - Napište do
moveCircle
logiku, která bude kontrolovat, zda-li hráč nevstoupil na pole s odměnou. Pokud vstoupí na pole s odměnou provede následující:- Zvýší skóre hráče.
- Odstraní odměnu z
game_board
. Tzn. nastaví dané pole na 0 a v HTML odebere obrázek odměny.
NPC
Nyní zkusíme do našeho programu přidat NPC (non-playable character), který bude hráče pronásledovat. K tomu potřebujeme několik změn v našem programu:
- Proměnné, které budou udávat pozici NPC v programu.
- Funkci, která se bude spouštět v pravidelných intervalech a která bude posunovat pozici NPC.
- Funkci, která bude schopna v našem
game_board
nalézt nejkratší cestu od hráče k NPC.
Spouštění v pravidelných intervalech
Vytvořte si funkci posunNPC
, kde bude docházet k posunu NPC a také se bude kontrolovat, zda-li NPC není na stejném poli s hráčem. Tato funkce se bude v JavaScriptu volat spomocí funkce setInterval
. Takže to bude vypadat nějak takto:
function posunNPC() {
// dopiště vlastní logiku
console.log("Function executed every second.");
}
setInterval(myFunction, 1000); // spouštěno každou sekundu
Hledání nejkratší cesty
Pro hledání nejkratší cesty využijeme algoritmus breath first search (BFS). Názorné vysvětlení algoritmu je možné vidět třeba zde. V lorem ipsum týmu na Repl.it je nyní program, který hledá nejkratší cestu v bludišti. Toto hledání realizuje funkce shortestPathSearch
. Zkusme se podrobně podívat na jednotlivé parametry funkce:
game_board
- dvourozměrné pole, tak jak jej máme v předchozím programu.xp
,yp
- souřadnice hráčex_npc
,y_npc
- souřadnice NPC
Import do souboru
Pro zpřehlednění programu můžeme hledání nejkratší cesty (funkci shortestPathSearch) přenést do samostatného souboru a v index.js ji naimportovat. Příklad toho jak se to v JavaScriptu dělá můžete vidět v následující otázce na StackOverflow popřípadě si můžete přečíst delší vysvětlení exportu a importu v JavaScriptu zde.
Projects
Formulář pro hodnocení výsledné aplikace.