Codemas - 20. den

Včera jsme do hry přidali úvodní obrazovku s tlačítkem pro spuštění hry. Dnes do hry přidáme závěrečnou obrazovku, kterou ukážeme v případě, že hráč hráči dojde čas. Konkrétní pravidla hry (jak se čas bude počítat) vymyslíme až na to budeme připraveni.

Čas se nám zatím stále nepočítá, ale to nevadí. Už to známe z předchozích dnů, ne vždy se nám všechno podaří naprogramovat za jeden den, někdy si musíme práci rozložit a provádět ji postupně.

Dnes to bude docela jednoduché, protože budeme částečně opakovat postup, který jsme prováděli včera s úvodní obrazovkou. Alespoň si trochu odpočineme, posledních pár dní bylo opravdu náročných.


Oprava

Než dnes začneme, musíme se chytit za nos. Ve včerejším kódu jsme měli chybu. Dnes už je včerejší článek opravený, ale kdo se každý den nemůže dočkat (většina?) a pustil se do kódování podle včerejšího článku ihned, bude mít v kódu asi stejnou chybu, jakou jsme tam měli i my.

Najděte prosím svoji funkci prepniObrazovku, ve které máme podmínku, která se ptá, zda se parametr obrazovka rovná textu 'uvod' nebo 'hra'. Ze včerejška v ní máme řádek:

} else if (obrazovka = 'hra') {

Chyba je samozřejmě v tom, že uvnitř podmínky bychom měli porovnávat pomocí tří (nebo dvou) rovnítek. Jedno rovnítko znamená operátor přiřazení a nemá v podmínce co dělat. I přes tuto chybu nám funkce včera fungovala, ale dnes v ní budeme dělat změny a chyba v přepínání obrazovek by se už projevila.

Správně má řádek vypadat takto (tři rovnítka místo jednoho):

} else if (obrazovka === 'hra') {

Celá, už opravená, funkce prepniObrazovku ze včerejška:

// přepínání obrazovky
function prepniObrazovku(obrazovka) {
  // nejprve všechny obrazovky skryjeme
  hra.uvod.style = 'none';      // úvod
  hra.element.style = 'none';   //herní plocha

  // podle parametru zobrazíme příslušnou obrazovku
  if (obrazovka === 'uvod') {
    
    // úvod je flexbox, nastavíme na flex
    hra.uvod.style.display = 'flex';

  } else if (obrazovka === 'hra') {
    
    // herní plocha je blokový prvek, nastavíme na block
    hra.element.style.display = 'block';
  
  }
}

Za chybu se omlouváme, snad se na nás Ježíšek nebude moc zlobit, když jsme na ni přišli hned druhý den. To se v programování bohužel občas stává. Nejhorší jsou chyby, které jsou kódu několik dní, týdnů, měsíců nebo i let a skrytě škodí, aniž by o nich někdo věděl. To se nás naštěstí netýká, Vánoce nejsou ohroženy.

Závěrečná obrazovka

Pojďme se ty pustit do té závěrečné obrazovky. Nejprve si ji připravíme v HTML. Uděláme to stejně jako s úvodní obrazovkou včera. Na stejnou úroveň, jako je <div id="hra"> a <div id="uvod"> do souboru index.html vložíme:

<div id="konec">
  <div class="obsah">
    <h2>Děkuji za pomoc</h2>
    
    <p>Došel ti čas a já už opravdu musím zachráněné dárky vzít a roznést je dětem pod stromeček. Tvé pomoci si opravdu vážím.</p>

    <p id="vysledek"></p>
    
    <p>Tvůj Ježíšek</p>

    <button id="znovu">Hrát znovu</button>
  </div>
</div>

Potřebujeme na ní aplikovat styl, ale ten už máme hotový. V pohodě si vystačíme s tím, že závěrečná obrazovka bude vypadat stejně jako ta úvodní. Vyhovuje nám stejné pozadí, styl písma i vzhled tlačítka. Stačí nám tedy v CSS použít tzv. vícenásobný selektor a říci, že stejný styl, jaký máme pro #uvod, chceme použít i pro #konec.

V CSS souboru style.css najdeme část, kde máme #uvod {…} a změníme selektor před složenými závorkami na #uvod, #konec {…}

#uvod,
#konec {
  display: none;
  justify-content: center;
  align-items: center;
  margin-left: auto;
  margin-right: auto;
  width: 900px;
  height: 600px;
  background-image: url('obrazky/pozadi.png');
  background-size: 100% 100%;
}

Protože máme nastaveno display: none;, tak nám samozřejmě závěrečná obrazovka zmizí (při startu hry je skrytá), ale budeme věřit, že je vše v pořádku a že to vypadá, jak chceme. Chcete-li se přesvědčit, můžete v CSS řádek s display: none; na chvíli smazat nebo uzavřít do CSS komentáře /* display: none; */.

S koncovou obrazovkou budeme potřebovat pracovat v JavaScriptu, takže už asi tušíte, co bude následovat. Ano, musíme si na ni někde uchovat odkaz získaný pomoci document.getElementById. A to stejné provedeme rovnou i s tlačítkem Hrát znovu.

Pokud jste se dívali pozorně, všimli jste si, že v závěrečné obrazovce máme i prázdný odstavec <p id="vysledek"></p>, kam budeme později vypisovat dosažené skóre. I na tento odstavec si uložíme odkaz.

Stejně jako pro úvodní obrazovky, všechny tyto odkazy si uložíme do objektu hra na začátku našeho programu:

// objekt pro hru
let hra = {
  element: document.getElementById('hra'),
  sirka: 900,
  vyska: 600,
  dalsiDarek: 150,
  skore: 0,
  skoreElement: document.getElementById('pocet'),
  hudba: document.getElementById('hudba'),
  zvukNaraz: document.getElementById('zvuk-naraz'),
  zvukSebrano: document.getElementById('zvuk-sebrano'),
  uvod: document.getElementById('uvod'),
  tlacitkoStart: document.getElementById('start'),
  konec: document.getElementById('konec'),
  tlacitkoZnovu: document.getElementById('znovu'),
  vysledek: document.getElementById('vysledek')
}

V objektu hra už toho začínáme mít celkem dost, ale neboj, mnoho dalšího už tam přidávat nebudeme.

Přepínání koncové obrazovky

Včera jsme do hry přidali funkci prepniObrazovku, která podle předaného parametru přepíná mezi úvodní obrazovkou a obrazovkou s herní plochou. Pojďme ji upravit tak, aby uměla přepínat i na naši nově přidanou koncovou obrazovku.

Na začátku funkce nejprve skrýváme všechny obrazovky (nastavujeme jim CSS vlastnost display na hodnotu none), takže sem musíme přidat i naši koncovou obrazovku.

V další části pak máme podmínku, která se ptá na obsah parametru, který do funkce předáváme. Když parametr obsahuje text "uvod", zapne se úvodní obrazovka, a v případě hodnoty "hra" se zase zapne obrazovka s herní plochou. Podmínku tedy rozšíříme i o hodnotu "konec", která způsobí zobrazení závěrečné obrazovky.

V souboru script.js najdeme funkci prepniObrazovku a upravíme ji následovně:

// přepínání obrazovky
function prepniObrazovku(obrazovka) {
  // nejprve všechny obrazovky skryjeme
  hra.uvod.style = 'none';      // úvod
  hra.element.style = 'none';   // herní plocha
  hra.konec.style = 'none';     // závěrečná obr.

  // podle parametru zobrazíme příslušnou obrazovku
  if (obrazovka === 'uvod') {
    
    // úvod je flexbox, nastavíme na flex
    hra.uvod.style.display = 'flex';

  } else if (obrazovka === 'hra') {
    
    // herní plocha je blokový prvek, nastavíme na block
    hra.element.style.display = 'block';
  
  } else if (obrazovka === 'konec') {
    
    // závěrečná obr. je stejně jako úvod flexbox, takže nastavíme na flex
    hra.konec.style.display = 'flex';
  
  }
}

Přidejme do našeho programu ještě jednu funkci a nazvěme ji třeba konecHry (ať to máme podobné, když už máme startHry). V této funkci přepneme na koncovou obrazovku a do odstavce s id="vysledek" zapíšeme dosažené skóre, aby hráč na konci uviděl, kolika dětem zachránil Vánoce.

Na konec script.js přidej:

// zobrazí závěrečnou obrazovku a vypíše do ní dosažené skóre
function konecHry() {
  // přepneme na závěrečnou obrazovku
  prepniObrazovku('konec');
}

Nyní potřebujeme přidat ještě výpis dosaženého skóre. Nechceme, aby hra ohlásila pouze strohé Skóre: 5, ale rádi bychom trochu osobnější zprávu. Zároveň chceme tuto zprávu měnit pro různé úrovně dosaženého skóre.

Skóre budeme vypisovat do prvku, na který máme uložený odkaz v hra.vysledek. Budeme zapisovat text, takže budeme měnit jeho vlastnost textContent.

Do funkce doplníme sérii podmínek, která podle skóre vloží do prvku různou zprávu. Celá funkce bude vypadat třeba takto:

// zobrazí závěrečnou obrazovku a vypíše do ní dosažené skóre
function konecHry() {
  // přepneme na závěrečnou obrazovku
  prepniObrazovku('konec');

  // podle dosaženého výsledku vypíšeme hlášku
  if (hra.skore === 0) {

    hra.vysledek.textContent = 'Bohužel jsi nechytil žádný dárek. Ale snaha byla.';

  } else if (hra.skore === 1) {

    hra.vysledek.textContent = 'Zachránil jsi pouze 1 dárek, ale i ta jedna rozzářená dětská očička za to určitě stojí.';

  } else if (hra.skore < 5) {

    hra.vysledek.textContent = 'Chytil jsi ' + hra.skore + ' dárky. Mohlo to být lepší, ale určitě to zkusíš znovu, že ano?';

  } else {

    hra.vysledek.textContent = 'Výborně, chytil jsi ' + hra.skore + ' dárků. Tolik dětí bude mít díky tobě radostné Vánoce.';

  }
}

Na závěr

Opět jsme ve stavu, kdy jsme napsali velký kus kódu, ale nevidíme výsledek a musíme počkat na zítřek, než dopíšeme druhou, nezbytně nutnou polovinu. Závěrečnou obrazovku budeme zobrazovat až ve chvíli, kdy nám dojde čas, ale nám zatím žádný čas neběží. To vyřešíme zítra.

Zatím musíme věřit, že jsme dnes napsali vše správně. Pokud si troufáte, můžete si kód vyzkoušet tak, že ve funkci otestujDarky do podmínky, která testuje, zda robot dárek sebral (a kde zvětšujeme skóre), přidáme podmínku ve stylu "je-li skóre rovno 3, zavolej funkci konecHry". Nezapomeň po vyzkoušení kód zase odstranit, dělal by nám neplechu zítra, až přidáme do hry počítání času.

Pro případ, že se ti dnes něco nepovedlo, kompletní kód hry po dnešních úpravách si můžeš prohlédnout zde.

Máš-li dotazy, diskutuj u příspěvku pro dnešní den ve facebookové události. Těšíme se na tebe opět zítra.