Autíčko

Ovládání z klávesnice

Došli jsme k poznání, že kód pro zachytávání stisků kláves:

document.addEventListener('keypress', function(event){
  if(event.key=== 'w' || event.key=== 'W'){
  zrychli();
  }
 //dalsi klavesy
 
});

není dokonalý - událost keypress je totiž ta chvíle, kdy je písmenko po zmáčknutí napsáno (např. do dokumentu). Proto se při držení klávesy vykoná jedna akce (například pohyb vlevo), chvíli se počká a pak se bude vykonávat opakovaně.

Proto by se v takto naprogramované hře dalo snadno podvádět - lze totiž počáteční prodlevu i kadenci opakování nastavit v Ovládacích panelech/klávesnice (mimochodem, dialog nastavení klávesnice - viz obrázek - se v aktuální verzi Windows 10 neliší od prastarých WindowsXP).

Dolů a nahoru

Budeme tedy sledovat jiné události - keydown a keyup - okamžik, kdy jde klávesa dolů (=je zamáčknuta) a kdy se vrací nahoru. Tyto události ovšem i pro dlouhé držení (např. chci dlouho zrychlovat autíčko) vykonají pouze jednou. Proto není žádoucí, aby volaly přímo akci pridej(). Místo toho si zkusíme představit, že máme tabulku, ve které je informace, zda je momentálně klávesa držena, či ne. Po zamáčknutí w by tabulka vypadala takto:

Klávesa Proměnná Zmáčknuta?
w zmacknutoZrychli true
s zmacknutoZpomal false
a zmacknutoDoleva false
d zmacknutoDoprava false

V kódu to bude (zde pouze pro klávesu w, zbytek doplňte sami :)) takto:

//deklarace globalni promenne
zmacknutoZrychli = false;
 
document.addEventListener('keydown', function(event){
//klavesa byla zmacknuta
  if(event.key=== 'w' || event.key=== 'W'){
  zmacknutoZrychli=true;
  }
 //todo:dalsi klavesy
});
 
document.addEventListener('keyup', function(event){
//klavesa byla odmacknuta
  if(event.key=== 'w' || event.key=== 'W'){
  zmacknutoZrychli=false;
  }
 //todo:dalsi klavesy
});

Po této úpravě samozřejmě nebude funkce zrychli() volána přímo zmáčknutím klávesy. Proto je potřeba tuto funkci volat v hlavním opakovaném cyklu (funkce render naplánovaná pomocí setInterval, resp. requestAnimationFrame)

//Funkce ktera bude volana znovu a znovu = herní loop
function render(){
 
//Ovlivneni na zaklade stavu klaves
if(zmacknutoZrychli){
 zrychli();
}
//todo: další akce
 
//todo přepočítání x,y na základě rychlosti - viz další část textu
 
//nastav aktualni stav do prvku
document.getElementById('monster').style.top=y+"px";
document.getElementById('monster').style.left=x+"px";
}
 
//Naplánování herního loopu každých 33ms
setInterval(render,33);

Poznámka: aby byla hra skutečně stejně hratelná pro všechny, je třeba pamatovat, že 33ms není úplně spolehlivých - mezi jednotlivými snímky může uplynout i víc času. Jako námět pro rozšíření bychom tedy mohli měřit dobu skutečně uplynulou od minulého snímku a přenásobovat tím přírustky k pozici (= jak daleko se auto pohne)

Rychlost

Dosud jsme autíčko pohybovali pouze ve chvíli zmáčknutí klávesy, a to jeho maximální rychlostí. Jak to ovšem funguje s reálnými pohybujícími se předměty? Rychlost se nezvyšuje skokově. Dokud držíme nohu na plynu, rychlost roste. Když nohu z plynu sundáme (nebo začneme brzdit), rychlost se začne snižovat (až klesne k nule).

Z programátorského hlediska budeme potřebovat v naší hře zavést novou proměnnou (případně dvě, pro každou ze souřadnic x,y) - rychlost. Měl by platit vzoreček:

polohaX_nova=polohaX_stara + rychlostX * uplynulyCas

zjednodušeně (spoléháme se na správnost časování intervalem):

polohaX=polohaX + rychlostX

což se dá napsat i způsobem:

polohaX+=rychlostX

Toto se odehraje v každém výpočtu snímku (funkce render). Rychlost není v km/h či m/s jak jsme zvyklí z reálného života - v našem kontextu má zřejmě jednotku „uražené pixely za dobu mezi dvěma snímky“

Setrvačnost

Pro ještě lepší dojem z autíčka zkuste rychlost ovlivňovat i přirozeným zpomalováním (aerodynamickým odporem, třením pneumatik). Pozor, nestačí prostě nějakou hodnotu od rychlosti odečítat - rychlost může být i záporná = v opačném směru! Musíte udělat podmínku, která rychlost snižuje, pokud je rychlost větší než 0 a zvyšuje, pokud je menší než 0.

Otáčení a rychlost jako vektor