2. Event Listenery
Co je to Event Listener
Když budeme programovat hru, tak budeme chtít aby ji mohl hráč nějak ovládat. Mohli bychom třeba chtít, že když hráč na klávesnici stiskne tlačítko 'A', tak se v naší hře něco stane (provede se nějaký kód). K tomuto účelu nám slouží event listenery. Event listenery si můžeme vytvořit pro různé akce, např. pro stisknutí klávesy, uvolnění klávesy, pohyb myši a tak podobně. Event listener čeká až se provede akce pro kterou jsme si ho vytvořili a až se provede tak se spustí nějaká funkce kterou jsme event listeneru přiřadili.
V následující ukázce vytváříme event listener který zajistí, že se při stisknutí tlačítka vypíše do konzole jakou klávesu jsme stisknuli. Pokud si následují kód zkopírujete a spustíte, tak se vám to samozřejmě nebude vypisovat někam přímo na stránku jako tady, ale budete si muset otevřít konzoli. V Google Chrome můžeme konzoli otevřít pomocí kombinace kláves CTRL + SHIFT + I, u jiných prohlížečů si to můžete vygooglovat pokud nevíte.
<head>
<meta charset="UTF-8">
</head>
<body>
<script>
// Následující řádek přidá event listener přímo na objekt který se jmenuje document, takže stisknutí tlačítka na klávesnici se provede na naší stránce vždy.
// Pokud bychom ale chtěli, tak event listener můžeme přidat třeba jen na nějaký element v naší stránce.
// Takže pokud bychom přidali event listener, který reaguje třeba na pohyb myši například jen na canvas, tak by se funkce kterou jsme event listeneru předali spouštěla jen když bude kurzor najetý na canvasu.
document.addEventListener("keydown", (e) => { // Jako druhý parametr předáváme při vytváření event listeneru funkci. Možná jste se s tímto zápisem funkce ještě nesetkali, jde v podstatě o zkratku kdy místo function() {} píšeme () => {}
// Kód v této funkci se bude spouštět pokaždé, když stiskneme nějakou klávesu.
// Následující řádek vypíše do konzole jakou klávesu jsme stisknuli:
console.log("Stiskli jste: " + e.key); // objekt e, který naše funkce přijímá jako parametr, obsahuje různé položky které můžeme využít třeba k určení toho, jakou klávesu uživatel stisknul
});
</script>
</body>
<head>
<meta charset="UTF-8">
<style>
/* základní nastylování canvasu */
canvas {
border: 2px solid #f7f7f7;
background-color: #252525;
}
</style>
</head>
<body>
<canvas width="400" height="400" id="MujCanvas"></canvas>
<script>
let canvas = document.getElementById("MujCanvas");
let ctx = canvas.getContext("2d"); // získání kontextu pomocí kterého budeme na canvas kreslit
// v těchto dvou proměnných budeme ukládat souřadnice kostky
let x = 180;
let y = 180;
// nastavíme kontextu barvu a tloušťku čáry kterou bude používat ke kreslení
ctx.fillStyle = "green";
ctx.strokeStyle = "lightgreen";
ctx.lineWidth = 4;
// na začátku musíme kostku vykreslit, protože jinak by se vykreslila až když bychom stiskli nějakou klávesu
ctx.fillRect(x, y, 50, 50);
ctx.strokeRect(x, y, 50, 50);
document.addEventListener("keydown", (e) => {
// při stisknutí klávesy, se pomocí switche zeptáme o jakou klávesu jde a podle toho posuneme kostku vertikálně, horizontálně a nebo vůbec pokud se nebude jednat o klávesu WASD
switch (e.code) { // Můžete si všimnout že v této ukázce nepoužíváme e.key ale e.code. Výhodou použití e.code je to, že se nemusíme starat o to jestli má uživatel zapnutý třeba CapsLock, NumLock atp.
case "KeyD": // při stisknutí klávesy 'D' posuneme kostku doprava pokud tam bude ještě místo
if (x < canvas.width-50) { // ptáme se jestli je souřadnice X menší než šířka canvasu - 50(šířka kostky)
x += 10;
}
break;
case "KeyA": // při stisknutí klávesy 'A' posuneme kostku doleva pokud tam bude ještě místo
if (x > 0) {
x -= 10;
}
break;
case "KeyW": // při stisknutí klávesy 'W' posuneme kostku nahoru pokud tam bude ještě místo
if (y > 0) {
y -= 10;
}
break;
case "KeyS": // při stisknutí klávesy 'S' posuneme kostku dolů pokud tam bude ještě místo
if (y < canvas.height-50) {
y += 10;
}
break;
}
// před vykreslením kostky musíme canvas vymazat, pokud bychom to neudělali tak by se kostka neposunula ale jen by se na canvas nakreslila další (klidně si tento řádek zkuste zakomentovat pokud jste si tento kód zkopírovali a spustili)
ctx.clearRect(0, 0, canvas.width, canvas.height);
// následující dva řádky vykreslí na canvas kostku a aby ji vykreslili na správné místo, tak k tomu použijí naše proměnné kam si ukládáme souřadnice kostky
ctx.fillRect(x, y, 50, 50);
ctx.strokeRect(x, y, 50, 50);
});
</script>
</body>
Jednoduchý příklad interakce s canvasem
V minulé ukázce jste viděli, jak se event listener vytváří. V další ukázce si ukážeme jednoduchý příklad, ve kterém budeme pomocí kláves WASD posouvat kostku po canvasu.
V tomto příkladu si do proměnných 'x' a 'y' ukládáme souřadnice kostky a při stisknutí určitých tlačítek hodnoty uložené v těchto proměnných měníme a pozice kostky se tím tedy mění. Po každém stisknutí tlačítka vymažeme canvas a kostku nakreslíme znovu aby se kostka po canvasu posunovala.
Určení souřadnic kurzoru myši
V některých hrách můžeme chtít aby naši hru hráč ovládal pomocí myši. Proto bychom chtěli nějak zjišťovat souřadnice kurzoru myši abychom věděli na jaké místo v canvasu uživatel kliknul.
Následující ukázka přidává na canvas event listener, který zajišťuje že pokud se myš na canvasu pohne tak se souřadnice kurzoru myši zobrazí v levém horním rohu canvasu jako text.
<head>
<meta charset="UTF-8">
<style>
/* základní nastylování canvasu */
canvas {
border: 2px solid #f7f7f7;
background-color: #252525;
}
</style>
</head>
<body>
<canvas width="400" height="400" id="MujCanvas"></canvas>
<script>
let canvas = document.getElementById("MujCanvas");
let ctx = canvas.getContext("2d"); // získání kontextu pomocí kterého budeme na canvas kreslit
// nastavíme si jak bude vypadat font který budeme v canvasu vykreslovat (více v Canvas Taháku)
ctx.font = "20px Arial";
ctx.textBaseline = "top";
ctx.fillStyle = "white";
// v této ukázce kódu přidáváme event listener jen na canvas, takže se funkce kterou event listeneru předáváme bude volat jen když bude kurzor najetý na canvasu
canvas.addEventListener("mousemove", (e) => {
// získání bounding obdelníku canvasu (použijeme ho k určení pozice canvasu na stránce)
let canvasBoundingRect = canvas.getBoundingClientRect();
// získání X souřadnice kurzoru myši (e.clientX obsahuje hodnotu souřadnice která se týká celé stránky, takže od ní ještě musíme odečíst pozici levé strany canvasu - k tomu používáme boundingRect)
let x = e.clientX - canvasBoundingRect.left;
x = Math.round(x); // canvasBoundingRect.left může být desetinné číslo, tak to ještě zaokrouhlíme ať se nám souřadnice na obrazovku vypisují pěkněji
// získání Y souřadnice kurzoru myši (e.clientY stejně jako e.clientX obsahuje hodnotu souřadnice celé stránky, takže od ní ještě musíme odečíst horní stranu canvasu)
let y = e.clientY - canvasBoundingRect.top;
y = Math.round(y);
// vymazání canvasu
ctx.clearRect(0, 0, canvas.width, canvas.height);
// vypsání souřadnic kurzoru myši do levého horního rohu canvasu
ctx.fillText("x: " + x, 5, 5);
ctx.fillText("y: " + y, 5, 30);
});
</script>
</body>
Kvíz
V této části jsme si ukázali jak můžeme spustit nějaký kód po proběhnutí nějaké akce, například po stisknutí tlačítka. U většiny her ale budeme chtít aby se nějaký kód prováděl i bez proběhnutí nějaké akce pro kterou jsem si vytvořili event listener. Proto se v příští části podíváme co je to Main Loop, kterému se také často říká Game Loop. Stejně jako v minulé části je tu pro vás připravený kvíz.