PHP týden Letní akce
Pouze tento týden sleva až 80 % na kurzy PHP. Lze kombinovat s akcí Letní slevy na prémiový obsah!
Brno? Vypsali jsme pro vás nové termíny školení Základů programování a OOP v Brně!

Hra v jQuery - Střelba na terč

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

Vítám vás u tohoto tutoriálu. Ukážeme si, jak vytvořit jednoduchou hru - střílení na terč - za pomoci jQuery a HTML&CSS.

Soubory

Nejprve si vytvoříme potřebné soubory. Budou to:

  • index.html
  • terc.css
  • terc.js

Dále budeme potřebovat soubory

  • bum.mp3
  • not.mp3
  • terc.png
  • crosshair.png

Tyto soubory naleznete v přiloženém archivu na konci článku.

Začínáme

index.html

Přejděme do souboru index.html. Otevřete si jej ve svém oblíbeném editoru a vložte zjednodušenou HTML kostru.

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>Terče</title>
</head>
<body>

</body>
</html>

Do hlavičky si nalinkujeme jQuery, jQuery UI (stačí JS, CSS nepotřebujeme) a naše soubory.

<script src="http://code.jquery.com/jquery-1.10.2.js"></script>
<script src="http://code.jquery.com/ui/1.10.4/jquery-ui.js"></script>
<script type="text/javascript" src="terc.js"></script>
<link rel="stylesheet" href="terc.css" type="text/css">

Jelikož budeme přehrávat zvuky při trefení (bum.mp3) i při netrefení (not.mp3), vytvoříme si 2 elementy audio. Kdo má starý prohlížeč, má smůlu :). Do části body proto vložíme následující kód.

<audio id="bum" src="bum.mp3"></audio>
<audio id="nic" src="not.mp3"></audio>

Dále budeme zobrazovat statistiky a zbývající čas. To uděláme jednoduše.

<h1 style="float: right">
  <span id="shot">0</span>:<span id="miss">0</span><br>
  <span id="time">90</span>
</h1>

V prvním span se budou zobrazovat fragy, ve druhém střely mimo a ve třetím zbývající čas s výchozí hodnotou 90.

No a na konec samozřejmě něco, čím budeme mířit.

<img id="crosshair" src="crosshair.png">

Styly

Základ už máme. Nyní přejděme do souboru terc.css, ve kterém budeme stylovat.

Nejprve tagy html a body. Jelikož budeme využívat celou plochu monitoru pro zobrazování terčíků, potřebujeme ji roztáhnout. Toho docílíme, když nastavíme width a height na 100%. Dále zrušíme okraje a to tak, že nastavíme margin na Opx. Pokud uživatel najede se zaměřovačem moc na kraj, vyskočí mu scrollbary, což také není zrovna nejlepší. Scrollbary schováme tak, že nastavíme overflow na hodnotu hidden. A jako poslední věc schováme kurzor. Nevím jak vám, ale mně tam celkem vadí. Jednoduše nastavíme cursor na none.

První část tedy bude vypadat takto.

html, body {
  height: 100%;
  width: 100%;
  margin: 0;
  overflow: hidden;
  cursor: none;
}

Přejdeme k zaměřovači. Zde toho nebude moc, pouze potřebujeme nastavit pozici na absolutní, aby se mohl "pohybovat jak bude chtít" a z-index na nějakou vyšší hodnotu (třeba 100000 :) ). Druhá část tedy bude vypadat nějak takto.

#crosshair {
  position: absolute;
  z-index: 100000;
}

Přejdeme k 3., poslední části. A to budou samotné terčíky. Pokud jste si již stáhli přiložený soubor a dívali se na obrázky, asi jste si všimli, že obrázek má 128px. To je docela dost, proto si jej zmenšíme pomocí CSS na nějakých 48px. Opět nastavíme absolutní pozici. Poslední část tedy bude vypadat takto

.terc {
  position: absolute;
  width: 64px;
  height: 64px;
}

Jak to bude fungovat

Nyní se konečně dostáváme k zajímavější části - a to jQuery. Přejdeme do souboru terc.js.

Začneme následující funkcí

$(function(){

});

A můžeme začít psát kód.

Browser-akce

Při hraní, hlavně takovýchto her celkem dost rozčilují výchozí browser-akce, jako je například přetahování obrázků, označování textu, kontextové menu... To vše povypínáme. Označování textu můžeme zakázat pomocí funkce .disableSelection() z jQuery UI. Pro zakázání kontextového menu a přetahování obrázků nabindujeme eventy dragstart a contextmenu. Do funkcí vložíme jednoduše return false;. Kód bude vypadat nějak takto

$(document)
  .disableSelection()
  .on("dragstart", "img", function() {
         return false;
       })
  .on("contextmenu", function(){
         return false;
       });

Zakázáno.

Zaměřovač

Nejspíše jste si všimli, že nám zaměřovač nějak nereaguje. Myslím, že je čas s ním trochu pohnout. Pohybovat s ním budeme tak, že mu budeme měnit vlastnosti LEFT a TOP podle toho, kde je právě kurzor myši.

Nabindujeme si event mousemove, funkci dáme parametr e. Poté jednoduše změníme vlastnosti na e.pageY a e.pageX (+px). Pro detail můžeme ještě odečíst hodnotu 24, aby myška seděla přesně na středu.

Na přidávání px si můžeme vytvořit funkci, můžeme ji pojmenovat např. px :).

function px(number)
{
  return number + "px";
}

Kód může vypadat nějak takto

$("body").mousemove(function(e){
   $("#crosshair")
        .css("top", px(e.pageY-24))
        .css("left", px(e.pageX-24));
});

Pokud si to nyní vyzkoušíte, zjistíte, že se zaměřovač pohybuje.

A teď si vyrobíme klikání. Nabindujeme si event click, funkci opět přidáme parametr e.

Pro výběr elementu použijeme funkci document.elemen­tFromPoint(x,y), jejíž výstup si uložíme do proměnné element. Místo X a Y dosadíme hodnoty z e.pageX a e.pageY. Pokud bychom ale někam klikli, zjistíme, že nám funkce vždy vrátí #crosshair. Je to kvůli z-index. Proto před voláním této funkce nastavíme z-index na -1 a potom jej vrátíme zpět.

Dále potřebujeme zjistit, zda má element třídu "terc" (terčík), nebo ne (střela mimo). To zjistíme pomocí funkce .hasClass() na proměnnou element.

Pokud tuto třídu má, jedná se o terčík a můžeme pokračovat. Terčík necháme "vybouchnout" pomocí funkce .effect. Efekt bude "explode" s dobou 500ms. Jelikož by se nám terčíky po delší době nashromáždily (funkce .effect nastaví po výbuchu display: none, takže tam pořád zůstává), zavoláme funkci pro odstranění elementu se zpožděním 500ms. Jako poslední věc spustíme zvuk "BUM" (pomocí .trigger("play")) a přičteme bod za trefu.

Pokud objekt není terčík, spustíme zvuk "NIC" a přičteme bod za střelu mimo.

Celý kód bude vypadat nějak takto

$("#crosshair").click(function(e){
    $(this).css("z-index", "-1");
    element = document.elementFromPoint(e.pageX, e.pageY);
    $(this).css("z-index", "10000");

    if($(element).hasClass("terc"))
    {
        $(element).effect("explode", false, 500);
        setTimeout(removeEl(element), 500);

        function removeEl(el)
        {$(el).remove();}

        $("#bum").trigger("play");
        $("#shot").text(parseInt($("#shot").text())+1);
    }
    else
    {
        $("#nic").trigger("play");
        $("#miss").text(parseInt($("#miss").text())+1);
    }
});
Terčíky

Tak, střílení nám funguje, ale pořád nemáme terčíky. Takže samé záporné body o_O. Musíme to napravit!

V proměnné generovani vytvoříme interval na 1 sekundu s voláním funkce generateNext (kterou si hned vytvoříme). Poté si vytvořte funkci generateNext.

Vytvoříme si ještě jednu funkci, která nám bude generovat náhodnou pozici.

function randomPosition(min, max) {
  return Math.floor(Math.random() * (max - min + 1)) + min;
}

Vytvoříme si proměnné posX a posY, do kterých si uložíme náhodou pozici terčíku. Náhodou pozici získáme takto - randomPosition(48, $("body").width()-48); (pro šířku. pro výšku nahradit width height).

Konečně vložíme terčík a to takto:

$("body").append('<img src="terc.png" class="terc" style="top:'+posY+'px;left:'+posX+'px;">');

Odečteme jednu vteřinu z odpočítávání a otestujeme, zda tam není nula. Pokud je, odstraníme všechny terčíky a ukončíme interval generovani.

Celá část tedy bude vypadat takto:

generovani = setInterval(generateNext, 1000);

function generateNext()
{
  posX = randomPosition(48, $("body").width()-48);
  posY = randomPosition(48, $("body").height()-48);

  $("body").append('<img src="terc.png" class="terc"style="top:'+posY+'px;left:'+posX+'px;">');

  $("#time").text(parseInt($("#time").text())-1);
  if($("#time").text() == "0")
  {
      $(".terc").remove();
      clearInterval(generovani);
  }
}

Výsledek:

Hra v jQuery – Střílení na terčíky

Hru si můžete vyzkoušet a v případě problémů porovnat se zdrojovými kódy v archivu.


 

Stáhnout

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

 

 

Článek pro vás napsal Daniel Vítek
Avatar
Jak se ti líbí článek?
7 hlasů
Primárně PHP programátor, rád si hraje s Arduinem a píše články do sekce Batch.
Všechny články v sekci
JavaScript zdrojákoviště - jQuery
Aktivity (2)

 

 

Komentáře
Zobrazit starší komentáře (3)

Avatar
Regedin the Immortal:27.8.2014 9:03

Super. opravdu pěkné jen jedna chyba že je ve funkci s přidáváním pixelů napsáno fuciton.

 
Odpovědět 27.8.2014 9:03
Avatar
Daniel Vítek
Tým ITnetwork
Avatar
Odpovídá na Regedin the Immortal
Daniel Vítek:27.8.2014 11:27

Díky :)

Chybku opravím.

Odpovědět 27.8.2014 11:27
Na síti působím už pěknou řádku let. Pokud budeš něco potřebovat, písni mi, pokusím se ti poradit :)
Avatar
lastp
Redaktor
Avatar
lastp:29.8.2014 18:26

Ve Firefoxu se nepřipočítává skóre kvůli chybě ReferenceError: removeEl is not defined

 
Odpovědět 29.8.2014 18:26
Avatar
ponuka6
Člen
Avatar
ponuka6:30.8.2014 10:56

nepochopil som ako hru ukoncim a zobrazim vysledok

 
Odpovědět 30.8.2014 10:56
Avatar
cihalavalentyn:30.8.2014 13:36

Přidal jsem terčům Class "clickable"
A upravil js.
if($(element)­.hasClass("clic­kable")) // Pokud je pod myší element s třídou "clickable"
{
$(element).re­moveClass("clic­kable")

A odstranil jsem problém s opakovaným klikáním.
Jinak super hra :D

Editováno 30.8.2014 13:36
 
Odpovědět 30.8.2014 13:36
Avatar
Daniel Vítek
Tým ITnetwork
Avatar
Odpovídá na ponuka6
Daniel Vítek:30.8.2014 20:06

Na to tam je odpočet těch 90 vteřin .....

Odpovědět 30.8.2014 20:06
Na síti působím už pěknou řádku let. Pokud budeš něco potřebovat, písni mi, pokusím se ti poradit :)
Avatar
Daniel Vítek
Tým ITnetwork
Avatar
Odpovídá na cihalavalentyn
Daniel Vítek:30.8.2014 20:06

Tak to bude jako domácí úkol :P

Díky :)

Odpovědět 30.8.2014 20:06
Na síti působím už pěknou řádku let. Pokud budeš něco potřebovat, písni mi, pokusím se ti poradit :)
Avatar
Patrik Pastor:16. dubna 13:57

if ($(element).has­Class('terc')){

if == false){
$(element).ad­dClass('noClic­k');
$(element).ef­fect('explode', false, 500);
setTimeout(re­moveEl(elemen­t), 500);
$(element).clas­sList

function removeEl(el){
$(el).remove();
}

$('#bum').trig­ger('play');
$('#shot').tex­t(parseInt($('#shot')­.text())+1);
}
}

css:

.noClick {
pointer-events: none;
}

Editováno 16. dubna 13:58
 
Odpovědět 16. dubna 13:57
Avatar
Odpovídá na Patrik Pastor
Patrik Pastor:16. dubna 13:59

if == false){
$(element).ad­dClass('noClic­k');

takhle je ta podminka, nevim, proc se to spatne zkopirovalo

 
Odpovědět 16. dubna 13:59
Avatar
Patrik Pastor:16. dubna 21:38

Mam jeste dotaz. Pokusil jsem se, aby pri kazde strelbe (uspesne) na tercik, se zrychli doba, kdy se dalsi tercik nahodne objevi (napriklad pri kazdem zasahu o 60ms), aby to bylo zajimavejsi. A tak jsem udelal globalni promennou "duration":

$(function(){
duration = 1000;
$(document)
//kod.......
//....

$('#crosshair')­.click(functi­on(e){
duration += 60;
//...
//....
}

generovani = setInterval(ge­nerateNext, duration);

}

problem ale je, ze promenna "duration" je sice globalni, ale presto se mi v dalsi funkci $('#crosshair')­.click(functi­on(e) NEzvysilo "duration", a tedy interval terciku je stale na 1 sekunde i pri zasahu. Nechapu tedy proc (sice je to ve funkci, ale promenna je prece globalni). Mohl by prosim nekdo vysvetlit jak je to s kontextem v jQuery, protoze v klasickem scritpu by mi prece globalni promenna prosla (jeji efekt), takze jak se lisi kontext v jQuery od klasickeho scriptu? diky za odpoved

 
Odpovědět 16. dubna 21:38
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 10 zpráv z 13. Zobrazit vše