Jak stworzyć prostą grę w przeglądarce internetowej? Część 2 (praktyczna).

O czym musisz wiedzieć zanim rozpoczniemy tworzyć grę?

  1. W grę możesz zagrać tutaj.
  2. Pierwsza część jest dostępna w lekcji: Jak stworzyć prostą grę w przeglądarce internetowej? Część 1 (teoretyczna).
  3. Lekcja ma na celu szybkie i łatwe nauczenie się podstaw, dlatego rozwiązania dostosowane do osób uczących się tworzenia gier.
  4. Gry na przeglądarkę internetową mogą być otwierane na wszystkich urządzeniach, które mają przeglądarkę internetową (np.: komputer, telefon, tablet itd.). Niestety nie w każdym urządzeniu wszystko będzie działało tak samo. Starsze wersje przeglądarek internetowych (np. Internet Explorer) nie będą poprawnie wyświetlać gry. Lekcja przygotowuje grę, która dobrze działa z przeglądarkami internetowymi wydanymi w ostatnich 6 latach  (w przypadku problemów zainstaluj najnowszą wersję Chrome), a problemy opisz w komentarzu pod tym wpisem. Lekcja skupia się na komputerach, dlatego nie jest dostosowana do urządzeń mobilnych (telefon, tablet). W przyszłości zostanie omówiony temat urządzeń mobilnych.
  5. Jeżeli cokolwiek zostanie zbyt słabo proszę opisz to komentarzu pod tym wpisem.
  6. Najlepszym sposobem na naukę jest praktyka czyli czym więcej tworzysz tym lepsza/lepszy jesteś. Nie kończ nauki tylko na czytaniu!
  7. Na końcu lekcji będzie dodana gra, którą będziesz mogła/mógł ściągnąć na swój komputer.
  8. W poprzedniej lekcji napisaliśmy, że kod gry musi:

    • pokazać (wczytać) obrazki (rekin, rybka, ocean);
    • wprawić w ruch rekina (w losowym miejscu) i wykryć krawędzie (koniec obszaru) gry;
    • wprawić w ruch rybkę (sprawdzić jaki klawisz jest wciśnięty).
    • wykryć złapanie rybki przez rekina (kolizje obu obrazków).

Jak umieścić kod gry?

Gra w przeglądarce internetowej to w rzeczywistości strona internetowa. Do jej stworzenia potrzebujemy języków w jakich tworzy się strony (czyli HTML, CSS, Javasript). Kod strony internetowej będzie wyglądał tak (kod z poprzedniej lekcji):

<!DOCTYPE html>
<html lang="pl">
    <head>
        <meta charset="utf-8">
        <title>Gra rybka</title>

    </head>
     <body>

         <canvas id="tu_rysuj" width="700" height="700" style="border: 1px solid black;">
            Niestety Twoja przeglądarka nie obsługuje gier HTML 5. Zaktualizuj przeglądarkę internetową.
        </canvas>
    </body>
</html>

Zwróć uwagę, że można poprawić czytelność kodu poprzez jego odpowiednie z formatowanie np. użycie wcięć:

<head>
   <meta charset="utf-8">
   <title>Gra rybka</title>

</head>

Dzięki temu łatwiej zauważyć, że w sekcji „head” mamy tytuł strony („<title>Gra rybka</title>„).  Jest kilka szkół formatowania kodu, ale my w tej lekcji będzie stosować głównie wcięcia ( więcej o formatowaniu kodu).

Każdy język ma swoje zadanie (podstawy tworzenia stron internetowych). Kod w języku Javascript będzie odpowiadał za animację gry (poruszanie się rybek), wykrywanie kolizji (złapanie rybki przez rekina), poruszanie rybką itd.

Musimy teraz poinformować przeglądarkę internetową o tym, że będzie miała do czynienia z językiem Javascript. Można to zrobić za pomocą znacznika <script>. Kod Javascript powinien być pomiędzy znacznikiem otwierającym <script> i znacznikiem zamykającym </script>:

<script>

Kod Javascript

</script>

Znacznik umieszczamy przed znacznikiem zamykającym </body>.  Przeglądarka internetowa czyta kod linijka po linijce. Po napotkaniu znacznika <script> przerywa wczytywanie innych plików (np. obrazków) oraz wyświetlanie (generowanie) strony internetowej. Po przeczytaniu kodu Javascript przez przeglądarkę internetową wznawiane jest ściąganie innych plików i generowanie strony internetowej. Umieszczamy kod Javascript przed </body>, aby wczytywał się on jako ostatni i nie blokował wczytywania pozostałej części strony internetowej. 

Dobrą praktyką jest dodawanie kodu Javascript w oddzielnym pliku, bo dzięki temu można go wykorzystać jednocześnie na kilku stronach (więcej o tym w kolejnych lekcjach). My na potrzeby tej lekcji pozostaniemy przy umieszczaniu kodu Javascript wewnątrz strony internetowej.

Przeglądarka internetowa czyta kod Javascript i na jego podstawie tworzy (generuje) stronę internetową. Te tłumaczenie kodu źródłowego na wygląd strony nazywa się interpretowaniem. Starsze przeglądarki internetowe nie znają wszystkich nowych słów (znaczników np. <canvas>) lub błędnie tłumaczą, dlatego strona nie zawsze dobrze się wyświetla lub działa. Nasza gra może nie działać na starszych przeglądarkach internetowych (np. Internet Explorer w wersji8). Dostosowanie ich do najstarszych przeglądarek wymaga dodatkowych rozwiązań, ale w tej lekcji skupimy się na najpopularniejszych przeglądarkach internetowych.

Bardzo ważne jest testowanie naszego kodu na różnych przeglądarkach internetowych, ponieważ mogą różnie tłumaczyć (interpretować) kod.

Co to jest zmienna, drzewo DOM, obiekt?

Zmienna

Pomiędzy znaczniki <script> i </script> dodajemy kod odpowiedzialny za obrazki (rekina, rybki, ocean). Obrazki możemy pobrać z pierwszej lekcji. Użyjemy „zmiennych”, które są w programowaniu bardzo ważne. Co to jest zmienna? W prawdziwym życiu przypomina karton, który jest podpisany i zawiera coś, np.: karton telewizor – zawiera tv, karton radio zawiera radio.

Oto przykład zmiennej w języku Javascript:

var nazwa_zmiennej="zawartość zmiennej";

var karton_tv="telewizor";

„Var” mówi (deklaruje) przeglądarce internetowej, że ma do czynienia ze zmienną. Jest to tzw. „słowo kluczowe”, które pozwala przeglądarce internetowej łatwiej zrozumieć kod. Powinno być używane wyłącznie do pokazywania (deklarowania), gdzie programista stworzył zmienne (podpisał karton). Są wyjątki i różnice przy zmiennych, ale o tym w innej lekcji.

Następnie mamy nazwę naszej zmiennej („karton_tv„), a  po znaku równości zawartość zmiennej (czyli „telewizor”). Znak równości jest nazywany operatorem przypisania, bo przypisuje „telewizor” do „kartonu z tv”.

Zwróć uwagę, że na końcu znajduje się średnik (;), a zawartość zmiennej jest w cudzysłowach („”) lub pojedynczych cudzysłowach (”). Często początkujący programiści zapominają o tym, a to powoduje błędy. Cudzysłów mówi przeglądarce internetowej, gdzie zaczyna i kończy się zwykły tekst. Cudzysłowy są konieczne, aby móc także użyć np. spacji (np. var miasto=”Jelenia Góra”;). Średnik  mówi o zakończeniu kodu dotyczącego zmiennej.

Pamiętaj, aby nazwa zmiennej zawsze mówiła co zawiera (przy długim kodzie będzie to bardzo pomocne). Nazwa zmiennej nie powinna zawierać spacji i kropek, dlatego używaj podkreślenie przy dłuższych nazwach, np.: var aktualna_data="19 lipca 2016";. Nie rozpoczynamy nazw zmiennych od cyfr (np. var 6zawodnik="publiczność") i nie używamy słów kluczowych w nazwach (np. var var="zmienna"). Wielkość liter ma znaczenie, dlatego zmienna var pies="jamnik", a zmienna var Pies="jamnik" to nie to samo!

W kolejnych lekcjach dowiesz się jak kartony (zmienne) trzymać w jeszcze jednym pojemniku. Dzięki temu nie będziesz miał bałaganu w kodzie. Przeglądarka internetowa może zgłupieć jak spotka dwa kartony (zmienne) o tej samej nazwie (np. telewizor) w tym samym miejscu.

A teraz przykład zastosowania zmiennej:

var bitwa_pod_Grunwaldem="15 lipca 1410";

Drzewo DOM

Każda strona internetowa składa się z elementów np.: zdjęć, nagłówków, tekstów. Do dodania do strony zdjęcia czy nagłówka używamy znaczników HTML, np.: <img src=”nazwa_zdjecia.jpg”>, <h1> Nagłówek </h1> itd. Te elementy tworzą coś w rodzaju odwróconego drzewa, często jest nazywane drzewem DOM (kliknij, aby powiększyć):

Znaczniki HTML tworzące odwrócone drzewo

Obiekty drzewa to znaczniki użyte na stronie, np.: <html>, <head>, <title> (spójrz na kod w punkcie „Jak umieścić kod gry?”). Drzewo to jest tworzone zgodnie z obiektowym modelem dokumentu (ang. Document Object Model – DOM). Przeglądarka internetowa czyta kod i na jej podstawie tworzy drzewo. Na samej górze jest obiekt „DOCUMENT”, który oznacza całą stronę internetową. Dzięki temu możemy edytować wszystkie elementy strony za pomocą języka Javascript, a dostęp uzyskujemy za pomocą obiektu „Document” i odpowiedniego kodu.

Obiekt

Język Javascript opiera się na obiektach. Czym są te obiekty? Obiekty mogą przypominać rzeczy ze świata rzeczywistego, np. samochód.  Obiekty zawierają dużo informacji o sobie. Mają one zazwyczaj te informacje pogrupowane jako:

  • właściwości;
  • metody;
  • zdarzenia.

Właściwości obiektu przechowują jakieś informacje o obiekcie. Zawierają nazwę (kolor karoseri) i wartość (czerwony). Inne przykładowe właściwości amochodu: liczba drzwi, liczba koni mechanicznych itd. Właściwości przechowują jakieś informacje o obiekcie. Ustawmy kolor karoserii:

samochod.kolor_karoserii="czerwony";

Zwróć uwagę na kropkę pomiędzy obiektem samochód, a właściwością kolor_karoserii. To właśnie kropka pozwala na skorzystanie z właściwości samochodu.

Metody wykonują jakieś zadanie, np. otwórz drzwi („otworz_drzwi('tylnie')„), sprawdź czy włączone światła („sprawdz_czy_wlaczone_swiatla()„), itd. Użycie metody „otwarcie drzwi kierowcy” wygląda tak: 

samochod.otworz_drzwi('od_strony_kierowcy');

Zdarzenia są przydatne do sprawdzenia czy coś zostało zrobione, np. czy został wciśnięty przycisk:

przycisk.click= URUCHOM KOD

Jeśli „przycisk” zostanie kliknięty (zdarzenie „click„) to zostanie uruchomiony kod.

Dodanie nowego obrazka do strony wymaga kodu: „document.createElement('img');". Co on oznacza? „Document” oznacza stronę internetową, a metoda „createElement(‚img’)” dodaje nowy element do strony. Tym elementem jest obrazek (img – skrót od angielskiego image czyli obrazek).

Język Javascript ma dużo już stworzonych obiektów (np. „document”) i metod oraz właściwości, a dzięki temu sami nie musimy ich tworzyć. Oczywiście możemy tworzyć swoje obiekty i metody oraz właściwości, ale o tym będzie w innej lekcji ;-).

Jak dodać obrazki?

W języku HTML obrazki dodajemy poprzez kod „<img src="ocean.png">„. Angielski skrót „img” mówi przeglądarce, że będzie miała do czynienia z obrazkiem (image). „Src” to skrót z angielskiego „source” (źródło) i mówi przeglądarce, gdzie jest obrazek. Po znaku równości podajemy nazwę obrazka (ocean.png). W naszym przypadku podajemy wyłącznie nazwę obrazka, ale czasem konieczne jest też podanie miejsce przechowywania obrazka (folder).

Oto kod odpowiedzialny za dodanie obrazków w języku Javascript (za chwilkę wyjaśnienie co robi):

var ocean=document.createElement('img');
ocean.src = 'ocean.png';

var rybka=document.createElement('img');
rybka.src = 'rybka.png';

var rekin=document.createElement('img');
rekin.src = 'rekin.png';

Tworzymy trzy zmienne: ocean, rybka, rekin (var rekin).

Następnie do zmiennej przypisujemy kod, który dodaje obrazek do strony („document.createElement('img');"). Trzeba jeszcze podać nazwę obrazka, którego ma użyć przeglądarka internetowa (ocean.src = 'ocean.png';).

Skąd tak dziwna konstrukcja (ocean.src = 'ocean.png';)? Kod „var ocean=document.createElement('img');" dodaje obrazek w specyficzny sposób. Po takim kodzie zmienna „ocean” prowadzi do obiektu obrazka (<img>). Jak każdy obiekt posiada właściwości (np. samochód ma właściwość kolor karoserii) . Skoro to obrazek to na pewno ma właściwość w postaci źródła (src). Ustawienie źródła obrazka (jaki to plik) możliwe jest za pomocą kropki „ocean.src=”, następnie podajemy nazwę naszego pliku. 

Ten kod dodaje obrazki, ale jeszcze ich nie wyświetla na ekranie gry. Tym zajmiemy się później.

Cały kod:

<!DOCTYPE html>
<html lang="pl">
    <head>
        <meta charset="utf-8">
        <title>Gra rybka</title>

    </head>
     <body>

         <canvas id="tu_rysuj" width="700" height="700" style="border: 1px solid black;">
            Niestety Twoja przeglądarka nie obsługuje gier HTML 5. Zaktualizuj przeglądarkę internetową.
        </canvas>
        <script>

          var ocean=document.createElement('img');
                          ocean.src = 'ocean.png';

                         var rybka=document.createElement('img');
                         rybka.src = 'rybka.png';

                         var rekin=document.createElement('img');
                        rekin.src = 'rekin.png';


        </script>
    </body>
</html>

Jak  wprawić w ruch rekina  i wykryć krawędzie?

Rekin będzie się poruszał na ekranie gry zwanym płótnem (więcej o tym w pierwszej lekcji). Wiemy z poprzedniej lekcji, że nasze płótno (ang. canvas) ma szerokość 700 pikseli i wysokość na 700 pikseli. Piksel to punkt na ekranie komputera i często jest zapisywany jako „px” (ang. skrót od słowa pixel).

Jak wytłumaczyć przeglądarce internetowej, gdzie ma narysować naszego rekina? Trzeba jej podać wysokość i szerokość na jakiej ma pojawić się rekin. Szerokość nazywana jest współrzędną x, a wysokość współrzędną y. Ekran gry przypomina układ współrzędnych znany z matematyki (kliknij, aby powiększyć):

Oś współrzędnych z zaznaczonymi punktami

Nasz układ współrzędnych ma 7 pikseli (szerokość) na 6 pikseli (wysokość). Zauważ, że szerokość rośnie z lewej do prawej strony (od 0 do 7), ale wysokość już z góry w dół (0-6, w matematyce jest odwrotnie).

Dla przeglądarki prawy górny róg (pierwszy czerwony punkt) ekranu gry znajduje się w punktach 0,0 (szerokość i wysokość), a dolny lewy róg w punktach 7,6 (pomarańczowy kolor).

Współrzędne (szerokość i wysokość) dla:

  • niebieskiego punktu to 3,3;
  • drugiego czerwonego punktu to 6,2;
  • zielonego punktu to 7,2;
  • żółtego punktu to 6,5;
  • pomarańczowego punktu to 7,6.

W ten sposób możemy wytłumaczyć przeglądarce internetowej, gdzie ma wyświetlić rekina. Przechodzimy do kodu, utwórzmy dwie zmienne ze współrzędnymi prawego rogu zdjęcia rekina:

var polozenie_rekina_x=500;
var polozenie_rekina_y=250; 

Tworzymy zmienną na jakiej szerokości ma pojawić się rekin („var polozenie_rekina_x=500") oraz na jakiej wysokości (var polozenie_rekina_y=250;).

Dodajmy od razu wysokość (współrzędna y) na jakiej jest rybka:

var polozenie_rybki=10; 

oraz stwórzmy zmienną „stan_gry”, która będzie przechowywała cyfrę (omówiona zostanie później):       

var stan_gry=0;   

Cały kod:

var polozenie_rekina_x=500;
var polozenie_rekina_y=250;
var polozenie_rybki=10; 
var stan_gry=0; 

Teraz trzeba wprawić w ruch naszego rekina, a do tego będzie potrzebny dłuższy kod. Dobrze jest dłuższy kod umieścić w funkcji (czyli zbiorze poleceń dla przeglądarki internetowej, który ma wykonać jakiś cel – poruszyć rekina).

Przeglądarka internetowa zna wiele słów z języka Javascript, jednym z nich jest słowo „function”. Jest to słowo kluczowe, czyli używamy go tylko do tego, aby pokazać przeglądarce internetowej, gdzie jest funkcja. Jak tworzymy funkcje?

function NAZWA_FUNKCJI()
{
KOD_COŚ_ROBI;
}

Zwróć uwagę na nawiasy „()” oraz „{}” i średnik „;„. Tworzymy nasz kod:

function poruszaj_rekinem()
{
rysuj_rekina();
}

Funkcja to zbiór poleceń do wykonania, ale bez rozkazu nie zostanie zrobione nic. Trzeba przeglądarce internetowej powiedzieć kiedy ma je wykonać poprzez kod: „nazwa_funkcji();".  Zauważ, że ten kod jest bez słowa „function” (przykład w naszym kodzie to „rysuj_rekina()„).

Kod jeszcze nic nie robi, ale wkrótce go rozszerzymy. Poruszając rekinem musimy sprawdzić czy przypadkiem nasz rekin nie jest poza obszarem płótna (ekran gry ma szerokość i wysokość: 700px na 700px). W tym celu przeglądarka internetowa musi poznać położenie rekina, a my musimy dać jej instrukcję co ma zrobić, np.

Jeśli pensja jest większa od 5000 wyświetl napis „dobrze zarabiam”, a w przeciwnym wypadku „słabo zarabiam”. Jak to zdanie przetłumaczyć przeglądarce internetowej?

var pensja= 1200;
if(pensja>5000)
{
console.log("Dobrze zarabiam");
}
else
{
console.log("Słabo zarabiam");
}

Najpierw tworzymy zmienną „pensja” i przypisujemy do niej zawrotną kwotę w postaci 1200. Następnie używamy słowa kluczowego „if” (po polsku „jeśli”). Mówi ono przeglądarce internetowej, że będzie musiała sprawdzić czy jest spełniony warunek (pensja>5000). W nawiasach klamrowych („{kod}„) określamy kod, który ma się wykonać po spełnieniu warunku. W sytuacji nie spełnienia warunku przeglądarka internetowa przechodzi dalej i spotyka słowo kluczowe „else” (w przeciwnym razie), które zawiera informację co ma zrobić jak warunek nie jest spełniony.

Do czego służy kod console.log("jakiś tekst")? Służy on do wyświetlenia komunikatu w konsoli (narzędzie w przeglądarce internetowej). Dostęp do konsoli jest możliwy w większości nowoczesnych przeglądarek internetowych za pomocą przycisku na klawiaturze F12. Wyświetla on nowe okno z zakładką „konsola”. Tam pojawiają się komunikaty ("Słabo zarabiam")wysłane prze programistę. Jest to często stosowana technika przez programistów do badania działania kodu. W konsoli możemy też wpisywać kod Javascript, a przeglądarka internetowa go zrealizuje. Oto zrzut ekranu z przeglądarki internetowej Firefox 47 (kliknij, aby powiększyć):

Zurzt ekranu ze strony Stolica Kujaw oraz włączona konsola

Wróćmy do naszego kodu poruszającego rekinem. Granice płótna  (szerokość 700 px i wysokość 700 px) wyznaczają obszar gry widoczny dla Internauty. Lewa granica ma jest w punkcie „0”, a prawa w punkcie „700”. Rekin będzie wypływał z prawej strony w kierunku lewej. Po przekroczeniu lewej granicy (współrzędna x w punkcie 0) rekin powinien być przesunięty za prawą granicę ( za punkt 700). Oto granice na obrazku (kliknij, aby powiększyć):

Granice gry (prawa i lewa), na obrazku jest także rekin i rybka

Podając pozycje rekina podajemy współrzędne prawego górnego rogu zdjęcia. Rekin ma szerokość (200 px) i wysokość (103 px). Możemy wymiary zdjęcia sprawdzić zapisując obrazek rekina na pulpicie komputera i klikając na nim prawym przyciskiem myszy (wybieramy „właściwości” i zakładkę „szczegóły”). W pierwszej lekcji wspomnieliśmy, że zdjęcia mają kształt prostokąta lub kwadratu, więc prawy górny róg zdjęcia z rekinem jest w miejscu, gdzie nie widać rekina. Więcej wyjaśnia obrazek (kliknij, aby powiększyć):

Wymiary rekina

Zwróć uwagę, że prawy górny róg obrazka zaczyna się w punkcie 400, a kończy w punkcie 600 (zdjęcie ma szerokość 200 px).

Nasz kod poruszający rekinem będzie sprawdzał położenie rekina i:

  • w przypadku przepłynięcia przez rekina lewej granicy (0) będzie go przenosił za prawą granicę (700);
  • rekin znajdujący się za prawą granicą będzie miał losowaną wysokość na jakiej ma wypłynąć z prawej strony.

Kod musi mieć taką strukturę:

1. Sprawdź czy rekin jest za lewą granicą (0):

1.1 Jeśli tak to przesuń go za prawą granicę (700);

1.2 Jeśli nie to sprawdź czy jest za prawą granicą (700).

1.2.1 Jeśli jest za prawą granicą (700) to wylosuj wysokość na jakiej ma pojawić się rekin i przesuń go, aby nie był za granicą (700-10).

1.2.2 Jeśli nie jest za prawą granicą przesuń go o 10 pkt. i narysuj.

Oto kod funkcji, która wprawia w ruch rekina:

 function poruszaj_rekinem()
{
  if(polozenie_rekina_x<=-200)
  {
  polozenie_rekina_x=700;
  }
  else
  {
     if(polozenie_rekina_x>=700)
     {
     polozenie_rekina_x-=10;
     polozenie_rekina_y=Math.floor((Math.random() * 597) + 1);
     }
     else
     {
     polozenie_rekina_x-=10;
     rysuj_rekina();
     }
       }
}

Wpierw tworzymy nową funkcję (function poruszaj_rekinem()), następnie sprawdzamy czy rekin przeszedł cały przez lewą granicę (if(polozenie_rekina_x<=-200)). Badamy tutaj czy lewy górny róg obrazka z rekinem jest większy lub równy -200. Dlaczego taka liczba? Granica jest ustawiona w punkcie 0 (współrzędna x), a długość rekina wynosi 200. Jeśli chcemy, aby sprawdzenie odbywało się po tym jak cały rekin zniknie z ekranu gry to musimy od 0 (lewa granica) odjąć 200px (długość rekina).

Jeśli rekin przeszedł przez lewą granicę to trzeba ustawić go za prawą granicą (polozenie_rekina_x=700;), bo rekin będzie pływał od prawej do lewej strony.

Warunek „if” sprawdza czy rekin jest  za prawą granicą if(polozenie_rekina_x>=700). Jeśli położenie rekina jest równe lub większe niż 700 px (polozenie_rekina_x>=700) trzeba  sprawić, aby warunek przestał być prawdziwy. W przeciwnym razie rekin zostałbym za prawą granicą. Zmieniamy położenie rekina poprzez przesunięcie go o 10 punktów w lewą stronę (polozenie_rekina_x-=10;). Zauważ, że oprócz znaku równości jest też minus („-=„). Co to oznacza? Od przechowywanej liczby w zmiennej polozenie_rekina_x jest odejmowana wartość „10”. Inny przykład:

var liczba_wojewodztw=16;

liczba_wojewodztw+=1;

liczba_wojewodztw;

Najpierw do zmiennej „liczba_wojewodztw" dopisujemy liczbę 16. Następnie dodajemy do tej liczby 1 („liczba_wojewodztw+=1;„).  Teraz zmienna przechowuje liczbę 17.

Skoro przesunęliśmy rekina za prawą granicą to możemy mu wylosować wysokość na jakiej się pojawi (polozenie_rekina_y=Math.floor((Math.random() * 597) + 1);). 

Zmienna „polozenie_rekina_y” przechowuje wysokość na jakiej będzie prawy górny róg zdjęcia z rekinem. Do tej zmiennej przypisujemy losową liczbę z przedziału 0-597. Dlaczego nie 700 (dolna granica ekranu gry)? Jeśli wylosowana zostałaby liczba powyżej 597 to nie byłby widoczny cały rekin. Ma on wysokość 103 px, więc 597 + 103 = 700 (dolna granica). Pojawienie się rekina powyżej punktu 597 spowoduje, że będzie on częściowo pływał poza obszarem gry (przekroczy dolną granicę w punkcie 700).

Język Javascript, aby ułatwić pracę ma już stworzone obiekty, a jednym z nich jest obiekt „Math”. Dzięki temu możemy robić różne matematyczne obliczenia, np.

var liczba=Math.floor(500,23);

Będzie zwracał liczbę całkowitą z liczby „500,23” czyli zwróci 500. Zwróć uwagę, że zawsze piszemy „Math” z wielkiej litery! Jeśli chcemy losować liczby to pomocny będzie kod „Math.random()„, który zwraca liczbę z przedziału od 0 do 1 (ale, nigdy to nie jest 1!):

var liczba=Math.random();

Jeśli chcemy losować liczbę z innego przedziału niż 0 i 1 musimy pomnożyć wynik losowania, np. chcąc wylosować liczbę z zakresu od 1 do 6 musimy napisać taki kod:

var liczba=(Math.random()*6)+1;

Zwróć uwagę, że dodaliśmy jedynkę na końcu, ponieważ losowanie może zwrócić liczbę poniżej 1. My chcemy losować liczby z przedziału 1-6. Dodając jeden do wylosowanej liczby mamy pewność, że liczba nie będzie mniejsza niż 1.

Math.random” nigdy też nie losuje 1, więc nie jest możliwe wylosowanie maksymalnego wyniku czyli 6. Dodając jeden do wyniku mamy szansę wylosowania 6.

Losowana liczba będzie zawsze ułamkiem, więc musimy ją zamienić na liczbę całkowitą. Do tego użyjemy „Math.floor„.

var liczba=Math.floor((Math.random()*6)+1);

Jeśli żaden z warunków („if(polozenie_rekina_x<=-200)" oraz "if(polozenie_rekina_x>=700)") nie jest spełniony to znaczy, że rekin jest na ekranie gry.

Rekin znajdujący się na planszy jest przesuwany o 10 punktów („polozenie_rekina_x-=10;") oraz rysowany na ekranie gry („rysuj_rekina()").  Jeśli będziemy co chwilę uruchamiać funkcję poruszającą rekinem („poruszaj_rekinem()„) to będzie on przesuwany do czasu, aż przekroczy lewą granicę. Jak uruchamiać co chwilę funkcję będzie w dalszej części tej lekcji.

UWAGA: Dobrą praktyką jest umieszczanie współrzędnych (wysokość i szerokość) w zmiennych. Dlaczego? W przypadku zmiany wielkości i szerokości ekranu gry (płótna) trzeba zmienić współrzędne w wielu miejscach. Gdyby współrzędne były przechowywane w postaci zmiennych zmniejsza się liczba miejsc do edycji.

Mamy konto na które wpływa pensja 2000 zł („var konto=2000;„) . Po wpłynięciu pensji („if(konto>=2000)„) musimy opłacić czynsz (1000 zł) i kupić żywność (500 zł).  Na końcu płacimy podatek od czynszu, który wynosi 10 proc. Od 1 tys. zł będzie to 100 zł („konto-100;„).

var konto=2000;

if(konto>0)
{
konto-=1000;
konto-=500;
konto-=100;

}

A co się stanie w sytuacji podwyżki czynszu (1500 zł)? Musimy zmienić kod w dwóch miejscach:

  • czynsz („konto-1500;„);
  • podatek od pensji („konto-150„).

Lepszym rozwiązaniem jest przechowywanie kwoty czynszu w zmiennej, bo wtedy wystarczy zmienić kod tylko w jednym miejscu („var czynsz=1500;„):

var konto=2000;
var czynsz=1500;

if(konto>=2000)
{
konto-=czynsz;
konto-=500;
konto-=czynsz*1/10;

}

Na potrzeby lekcji nie przypisywaliśmy wszystkich współrzędnych do zmiennych, aby móc łatwiej się zorientować w kodzie. W przyszłości jednak warto współrzędne trzymać w zmiennych.

Jak sprawdzić czy rekin złapał rybkę?

Sprawdzając czy rekin złapał rybkę musimy wykryć kolizję pomiędzy obydwoma obrazkami (prostokątami). Kod, który będzie to sprawdzał będzie umieszczony w funkcji (takie pudełko na kod ;-)). Oprócz zrobienia pudełka z kodem (napisania funkcji) trzeba go jeszcze uruchomić (wywołać), a to możemy osiągnąć za pomocą kodu: nazwa_funkcji(). Pozwala to decydować, kiedy chcemy uruchomić (wywołać) kod.  Funkcja umożliwia nam to, a także gromadzi cały kod w jednym miejscu. Dzięki temu edycja kodu jest łatwiejsza. Kolejność uruchomienia często ma ważne znaczenie dla poprawnego działania gier.

Rybka będzie pływać tylko od góry do dołu, a więc zmieniać będzie się tylko wysokość na jakiej się będzie pojawiać. Prawy górny róg zdjęcia z rybką będzie zawsze na szerokości w punkcie 290 (współrzędna x). Do rysowania rybki wrócimy później.

Zdjęcie rybki ma szerokość 80px czyli rybka zawsze jest w szerokości pomiędzy punktem 290 (prawy górny róg zdjęcia), a 370 (290 + 80 px długości zdjęcia). Jeżeli rekin pojawi się pomiędzy tymi punktami to znaczy, że mógł złapać rybkę:

polozenie_rekina_x>=290 i polozenie_rekina_x<=370;

 wspolrzedne2

Musimy jeszcze sprawdzić czy rekin i rybka są na tej samej wysokości (współrzędna y). Możemy to zrobić poprzez sprawdzenie czy rekin jest pomiędzy górnym i dolnym rogiem zdjęcia rybki. Dolny róg zdjęcia rybki jest oddalony od górnego o 79px (wysokość zdjęcia).

Jeżeli będzie sprawdzać czy rekin jest pomiędzy prawym górnym, a dolnym rogiem zdjęcia to będzie dochodziło do dziwnej sytuacji. Gra będzie mówiła, że rekin zjadł rybkę (kolizja obrazków) nawet nie będąc blisko niej. Długi ogon wydłuża obrazek (kliknij, aby powiększyć):

Wokół rybki jest zaznaczony kwadratowy obszar, który jest wysoki ze względu na długi ogon rybki. W tle ocean, a obok rybki rekin.

Na obrazku jest zaznaczony obszar, w którym obecność rekina będzie uważana za zjedzenie rybki.

Musimy wprowadzić poprawkę, która lepiej będzie sprawdzać złapanie rybki przez rekina. Zamiast badać czy rekin znalazł się pomiędzy prawym górnym, a dolnym rogiem zdjęcia zastosujemy punkt bliższy górnego rogu. Będziemy badać czy rekin znalazł się pomiędzy prawym górnym rogiem, a punktem oddalonym o 51 px. Skąd 51 px? Od górnego rogu do brzucha rybki jest około 51 px. Dlatego badając czy rekin i rybka musimy wprowadzić poprawkę. Nie będziemy badać  są na tej samej wysokości musimy zmniejszyć badaną wysokość z 79 na 51.

Zdjęcie rekina to prostokąt, dlatego górny róg zdjęcia nie znajduję się blisko rekina. Do sprawdzania kolizji pomiędzy rybką, a rekinem posłużymy się punktem na połowie wysokości zdjęcia rekina (wysokość zdjęcia to 103 px).

Będziemy sprawdzać czy środek zdjęcia rekina znajduję się pomiędzy górnym i dolnym punktem zdjęcia rybki (wysokość zdjęcia rybki to 79 px, ale my badamy kolizję do wysokości 51px). Środek zdjęcia rekina możemy obliczyć dodając połowę wysokość zdjęcia rekina do prawego górnego rogu zdjęcia. Przypominam, że wysokość na ekranie gry rośnie w dół (czyli prawy róg ma mniejszą liczbę niż dolny róg). A oto kod:

polozenie_rekina_y+52>=polozenie_rybki i polozenie_rekina_y+52<=polozenie_rybki+51

Środek wysokości rekina („polozenie_rekina_y+52„) musi równa lub wyżej niż prawy górny róg zdjęcia z rybką („polozenie_rybki„). Dodatkowo środek wysokości rekina („polozenie_rekina_y+52„) nie może być niżej niż dolny punkt zdjęcia rybki („polozenie_rybki+51„).

Gry mogą mieć trzy stany:

  • Gra nierozpoczęta;
  • W trakcie gry;
  • Gra zakończona.

My w naszej grze użyjemy dwóch stanów: „w trakcie gry” i „gra zakończona”. Stworzyliśmy do tego zmienną ?var stan_gry=0;?. Zero będzie oznaczać „w trakcie gry”, a dwa „zakończenie gry”.

Później będziemy mogli sprawdzić jaką liczbę zawiera zmienna stan_gry. Jeśli dojdzie do kolizji dwóch obrazków (zjedzenie rybki przez rekina) powinniśmy stan gry zmienić na 2 (zakończyć grę):
„var stan_gry=2”;

Sprawdzając czy rekin zjadł rybkę musimy sprawdzić kilka warunków jednocześnie, np. czy rekin jest w tej samej szerokości i wysokości co rybka. 

Kod będzie miał konstrukcję:

Jeśli (spełniony warunek 1 i spełniony warunek 2 i spełniony warunek 3 i spełniony warunek 4)
{
zmień stan gry
}

Zmiana stanu gry będzie możliwa jak wszystkie 4 warunki będą spełnione:

(spełniony 1 i spełniony 2 i spełniony 3 i spełniony 4).

Nie zostanie zmieniony stan gry, jeśli choć jeden z warunków nie będzie spełniony. W języku Javascript za ?i? służy znak „&&„.

Oto cały kod:
function wykryj_kolizje()
  {

  if(polozenie_rekina_x>=290&&polozenie_rekina_x<=370&&polozenie_rekina_y+52>=polozenie_rybki&&polozenie_rekina_y+52<=polozenie_rybki+51)
    {
    stan_gry=2;

    }
  }

Kod został wyjaśniony wcześniej, ale poniżej pomocna grafika (kliknij, aby powiększyć):

Obrazek pokazuje ramkę wokół rybki i zielony punkt przy rekinie. Punkt ten jest z przodu rekina na połowie jego wysokości.

Jeśli w czerwonej ramce znajdzie się zielony punkt to rekin złapał rybkę. Oto przełożenie na kod:

  • lewa czerwona granica – 290 (szerokość);
  • prawa czerwona granica – 370 (szerokość);
  • górna czerwona granica – polozenie_rybki (wysokość);
  • dolna czerwona granica – polozenie_rybki+51 (wysokość);
  • zielony punkt (rekin) – polozenie_rekina_x (szerokość) oraz polozenie_rekina_y+52 (wysokość).

Jak wprawić w ruch rybkę?

Gracz będzie mógł sterować rybką, dlatego musimy sprawdzić co wcisnął na klawiaturze i odpowiednio zareagować. Można to zrobić za pomocą konstrukcji sprawdzającej warunek (?if? i ?else?). Jest jeszcze inna możliwość ? konstrukcja „switch”. Polega ona na tym, że porównujemy dwie zmienne, a jak znajdziemy dopasowanie to jest uruchamiany odpowiedni kod. Załóżmy, że mamy sklep i Internauta może kupić w nim owoce. Wybrany przez internautę owoc przypisujemy do zmiennej ?koszyk?. Jak sprawdzić co wybrał?

var koszyk="jabłko";
switch(koszyk)
  {
  case "gruszka":
  console.log("gruszka");

  break;
  case "jabłko":
  console.log("jabłko");
  break;
  default:
  console.log("Nie ma w koszyku owocu!");
  break;
  }

Co ten kod robi? Tworzymy zmienną ?koszyk?, gdzie przechowujemy produkty wybrane przez Internautę. Do ?koszyka? wrzuciliśmy ?jabłko? („var koszyk="jabłko";"). Następnie porównujemy zawartość koszyka z możliwy opcjami (jabłko, gruszka itd.).

?Switch? to słowo kluczowe, które mówi przeglądarce internetowej, że będzie porównywać dwie zmienne. W naszym przypadku będzie porównywać ?koszyk? z opcjami ?jabłko?, ?gruszka?.
Słowo kluczowe ?case? (ang. przypadek) to sygnał dla przeglądarki, że wartość koszyka ma porównać z opcją umieszczoną w cudzysłowach („case ?gruszka?:„). Zauważ, że po opcji jest dwukropek, który mówi co zrobić w przypadku dopasowania zawartości koszyka do opcji (?gruszka?).

My poprosiliśmy, aby dodał słowo ?gruszka? do konsoli przeglądarki internetowej („console.log"gruszka");„). Może to jednak być dowolny kod. Następnie jest słowo kluczowe ?break;?, które nakazuje przeglądarce internetowej przerwanie porównywania zawartości ?koszyka? z innymi opcjami (oczywiście jak zmienna „koszyk” będzie pasować). Dlaczego? Jak dopasowaliśmy ?koszyk? do ?jabłko? to nie ma sensu dalej porównywać zmiennych (kazać pracować nad tym przeglądarce).

Na samym końcu jest słowo kluczowe ?default? (ang. domyślny), które mówi przeglądarce internetowej co zrobić w sytuacji braku dopasowania ?koszyka? do możliwych opcji (?jabłko?, ?gruszka?). Jest to bardzo ważne w programowaniu, aby przewidywać sytuację otrzymania zupełnie czegoś innego niż się spodziewaliśmy. ZAWSZE musimy spodziewać się, że znajdzie się tam zupełnie coś innego niż byśmy chcieli.

Konstrukcja ?switch? może być szybsza niż konstrukcja ?if i else?, dlatego ją poznaliśmy przy tworzeniu tej gry.

Nasza instrukcja ?switch? będzie sprawdzała jaki został wciśnięty klawisz i na tej podstawie będzie przesuwana rybka.

Funkcja może przyjmować z zewnątrz informacje, np. funkcja sklep może otrzymywać informację o koszyku:

var koszyk="marchew";

function sklep(zakupy)
   {
  console.log(zakupy);
   };

sklep(koszyk);

Na początku tworzymy zmienną „koszyk”, która przechowuje informacje o zakupach („var koszyk="marchew";„).

Następnie tworzymy funkcję sklep, która otrzymuje z zewnątrz informację o zakupach („function sklep(zakupy)„). Wykorzystuje ją do wyświetlenia w konsoli zawartości zakupów („console.log(zakupy);„).

Teraz „koszyk” musimy przekazać informację do „sklepu”. Wystarczy, że w miejscu „zakupy” dodamy naszą zmienną „koszyk”. Po uruchomieniu funkcji ("sklep(koszyk);") efektem będzie pojawienie się w konsoli napisu „marchew”.

W ten sposób możemy do funkcji przekazać informację jaki klawisz został wciśnięty. W języku Javascript każdy klawisz ma przyporządkowaną liczbę, np.: enter – 13; strzałka w górę – 38; strzałka w dół – 40; literka z – 122, cyfra 1 – 49 itd. Ta liczba jest nazywana kluczem klawisza (ang. key code) i możesz ją sprawdzić na stronie http://keycode.info/ (strona dostępna 14 lipca 2016 r.). A teraz czas na kod 🙂 :

function poruszaj_rybka(zdarzenie)
{          
klucz_klawisza = zdarzenie.keyCode;
}

Załóżmy, że mamy informację co zostało wciśnięte na klawiaturze (przekazywane przez obiekt „zdarzenie”). Przekazujemy tą informację do funkcji „poruszaj_rybka”, która musi wiedzieć co zostało wciśnięte. Następnie tworzymy zmienną („klucz_klawisza”), w której będziemy przechowywać liczbę klawisza.

Informacja o liczbie wciśniętego klawisza jest przekazywana w obiekcie „zdarzenie”, a możemy ją sprawdzić poprzez jego właściwość „KeyCode” (ang. klucz klawisza). Kod zwracający liczbę wygląda następująco: „zdarzenie.keyCode„.

Musimy napisać kod, który będzie sprawdzał (nasłuchiwał) co zostało kliknięte i przekazywał tą informację w postaci obiektu „zdarzenie”. Zajmiemy się tym później. Wróćmy teraz do kodu, który podejmuje decyzje w zależności od wciśniętego klawisza.

Oto kod poruszający rybkę:

function poruszaj_rybka(zdarzenie)
{           
klucz_klawisza = zdarzenie.keyCode;       
switch(klucz_klawisza)
   {
  
case 38:
  
if(polozenie_rybki<=0)
    
{
     polozenie_rybki=0;
     }
 
  else
   
  {
    
polozenie_rybki-=10;
    
}
  
break;
 
  case 40:
  
if(polozenie_rybki>=621)
    
{
    
polozenie_rybki=621;
   
  }
   else
    
{
    
polozenie_rybki+=10;
     }
  
break;
  
}
}      

Większość kodu została już omówiona. Do funkcji „poruszaj_rybka” przekazujemy informację, który klawisz został wciśnięty (ma go obiekt „zdarzenie”). Odczytujemy informację o liczbie klawisza („zdarzenie.keyCode;„) i przypisujemy ją do zmiennej „klucz_klawisza” („klucz_klawisza = zdarzenie.keyCode;„).

Następnie porównujemy liczbę („switch(klucz_klawisza)„) z możliwymi opcjami:

  • cyfra 38 oznacza, że został wciśnięty klawisz „strzałka w górę”;
  • cyfra 40 oznacza, że został wciśnięty klawisz „strzałka w dół”.

W zmiennej „polozenie_rybki” przechowujemy informację na jakiej wysokości jest rybka (współrzędna_y). Jeśli przekroczyliśmy górną granicę gry („polozenie_rybki<=0„) to przesuwamy rybkę na samą górę („polozenie_rybki=0;„). Zwróć uwagę na znak „<=„, który ma sprawdzać czy rybka przekroczyła granicę lub czy jest na niej. Jeśli rybka jest na granicy to pozostanie na niej („polozenie_rybki=0;„). Po przekroczeniu górnej granicy ekranu gry współrzędna y (wysokość) będzie na minusie, stąd badamy czy zmienna („polozenie_rybki„) jest mniejsza lub równa zeru.

Jeśli jednak rybka nie przekroczyła granicy to możemy spokojnie przesunąć w górę („polozenie_rybki-=10;„). Zwróć uwagę na operator („-=„), który służy do odejmowania od zmiennej („polozenie_rybki„) liczby 10. Dla wysokości wartości maleją od dołu do góry czyli czym mniejsza liczba tym wyżej jest rybka.

Co w sytuacji, kiedy jednak został wciśnięta „strzałka w dół” („case 40:„)? Wpierw musimy sprawdzić czy rybka nie przekroczyła dolnej granicy ekranu gry (współrzędna y = 700). Pamiętajmy, że „polozenie_rybki” przechowuje górny róg zdjęcia rybki. Rybka dotknie dolnej granicy ekranu znacznie wcześniej, dlatego trzeba sprawdzić czy dolna granica ekranu została przekroczona przez dolny róg zdjęcia rybki. Wiemy, że granica znajduje się w punkcie 700, a wysokość rybki to 79px czyli dla rybki granica będzie w punkcie 621 (współrzędna y to 700-79px wysokości zdjęcia rybki).

W zmiennej „polozenie_rybki” przechowujemy informację na jakiej wysokości jest rybka (współrzędna_y). Jeśli przekroczyliśmy dolną granicę ekranu gry („polozenie_rybki>=620„) to przesuwamy rybkę nad granicę („polozenie_rybki=620„). Zwróć uwagę na znak „>=„, który ma sprawdzać czy rybka przekroczyła granicę lub czy jest na niej. Jeśli prawy górny róg zdjęcia rybki („polozenie_rybki„) jest w punkcie 620 to tam zostanie („polozenie_rybki=620„).

Jeśli jednak rybka nie przekroczyła granicy to możemy spokojnie przesunąć ją w dół („polozenie_rybki+=10„). Do położenia rybki dodajemy 10 punktów.

Jak sprawdzić jaki klawisz został wciśnięty po wczytaniu strony internetowej?

Strona internetowa jest przechowywana przez obiekt „Document” w drzewie DOM. Jest jednak coś nad obiektem „Document”. Strona internetowa jest wczytywana w oknie (ang. window) i właśnie ten obiekt jest nad „Document”.

Obiekt „Window” daje nam nowe możliwości. W przyszłych lekcjach zostanie szerzej opisany, a my w naszej lekcji wykorzystamy go do dwóch rzeczy:

  • upewnienia się, że cała strona się wczytała;
  • do sprawdzania (nasłuchiwania) jaki przycisk został wciśnięty przez Internautę.

Język Javascript umożliwia sprawdzenie czy wczytało się całe okno (zdarzenie „window.onload”). Jest też zdarzenie wczytania dokumentu (strony) poprzez kod „document.onload”.

Dlaczego używamy „window.onload”? Zdarzenie „window.onload” oczekuje na wczytanie się także zdjęć i „strony w stronie” (iframe), a zdarzenie „document.onload” nie umożliwia nam tego. Dlaczego czekamy na wczytanie okna? W grach od lat stosuje się mechanizm „wczytywania gry”, który polega na przygotowaniu wszystkiego potrzebnego do grania (np. wczytuje grafikę, zmienne itd.). Nasze rozwiązanie jest prymitywne, ale w następnych lekcjach będzie rozwijane. Zapamiętajmy, że poniższy kod zostanie wykonany dopiero po wczytaniu okna:

window.onload=function()
{
console.log("robie coś");
}

Zauważ, że funkcja nie ma nazwy („function() { }„). Jest ona nazywana funkcją anonimową i wykona się po wczytaniu strony („window.onload„). Dlaczego trzeba zastosować funkcję anonimową? Bez niej kod („console.log("robie coś");„) wykonałbym się przed załadowaniem okno („window.onload„).

Wróćmy do obiektu „Window”. W jaki sposób  kazać przeglądarce internetowej sprawdzanie co się dzieje w obiekcie „Window”? Do tego celu użyjemy metody, która będzie sprawdzała (nasłuchiwała) jaki przycisk został wciśnięty przez Internautę. Kod:

window.addEventListener('keydown', poruszaj_rybka);

Co robi kod? Nakazuje w oknie („window”) sprawdzać („addEventListener”) czy został wciśnięty przycisk („keydown”) i jeśli tak to uruchomi funkcję „poruszaj_rybka”. Oto cały kod:

window.onload=function()
{
 window.addEventListener('keydown', poruszaj_rybka);
}

Jak wyświetlić (rysować) grę?

W pierwszej lekcji dodaliśmy do strony kod:

<canvas id="tu_rysuj" width="700" height="700" style="border: 1px solid black;">

Jest to płótno (ang. canvas) w którym pojawi się gra czyli  nasz ekran gry. Zwróć uwagę, że gra ma identyfikator (id=”tu_rysuj”). Po co on jest? Na jednej stronie może być kilka miejsc do rysowania (płócien), a przeglądarka internetowa potrzebuje informacji na którym ma wyświetlić (rysować) grę.

Musimy się teraz dostać w stronie internetowej (obiekt „document”) do płótna o id „tu_rysuj„. Najlepiej zrobić to poprzez już istniejącą metodę: getElementByID('podaj_nazwe_id'). Nasz kod będzie wyglądał teraz tak:

plotno=document.getElementById('tu_rysuj');

Do zmiennej „plotno” przypisujemy miejsce („tu_rysuj”), gdzie ma wyświetlić się gra.

Teraz trzeba powiedzieć przeglądarce internetowe czy będzie rysować grafikę 2d czy 3d. Będziemy rysować 2d (czyli zawsze będziemy widzieć rybki i rekina z tego samego ujęcia). Kod za to odpowiedzialny wygląda tak: „getContext('2d');„.  Zauważ, że jest to metoda, więc brakuje nam obiektu. A na jakim obiekcie ma rysować 2d przeglądarka? Przeglądarka musi wiedzieć,  że na obiekcie „plotno” ma rysować 2d („plotno.getContext('2d')„). Wszystko też przypiszmy do zmiennej („rysuj2d”), aby nie przepisywać ciągle tego długiego kodu :-):

rysuj2d=plotno.getContext('2d');

Animowanie gry

W pierwszej lekcji była mowa o animowaniu gry (rysowanie, ścieranie ekranu i ponowne rysowanie). W naszej grze zastosujemy kod:

setInteval(co_mam_uruchomic, co_ile_mam_uruchomic).

Słowo kluczowe „Setinterval” pozwala uruchomić co jakiś czas funkcję („co_mam_uruchomic„). Zwróć uwagę, że do uruchomienia tutaj funkcji nie potrzebujesz nawiasów „co_mam_uruchomic()”.

Uwaga: czas podaje się w milisekundach. Jedna sekunda to 1000 milisekund.  Nasz kod będzie uruchamiał funkcję „uruchom_kod” co 1/10 sekundy (czyli 100 milisekund):

setInterval(uruchom_gre, 100);

Łączymy kod z tym co nauczyliśmy się ostatnio:

window.onload=function()
{
plotno=document.getElementById('tu_rysuj');
rysuj2d=plotno.getContext('2d');
window.addEventListener('keydown', poruszaj_rybka);
setInterval(uruchom_gre, 100);
}

Po wczytaniu się okna („window.onload=function()„) przypisujemy do zmiennej „plotno” miejsce, gdzie ma wyświetlać (rysować) się gra („plotno=document.getElementById('tu_rysuj');„). Następnie do zmiennej „rysuj_2d” przypisujemy sposób rysowania („rysuj2d=plotno.getContext('2d');„).

Nie jest to najprzyjemniejszy kod dla oka, ale cóż… taki sposób został narzucony przez organizację W3C. Po prostu trzeba się go nauczyć na pamięć.

Na końcu sprawdzamy (nasłuchujemy) jaki klawisz został wciśnięty i po wciśnięciu uruchamiamy funkcję „poruszaj_rybka” („window.addEventListener('keydown', poruszaj_rybka);„). Następnie nakazujemy co 1/10 sekundy uruchamiać funkcje „uruchom_gre” („setInterval(uruchom_gre, 100);„).

Rysowanie grafiki

Musimy teraz dodać (narysować) ocean, rybkę i rekina do ekranu gry (płótna). Możemy to zrobić poprzez metodę „drawImage(nazwa_zmienej_z_rysunkiem; wspolrzedna_x; wspolrzedna_y)„. Podajemy współrzędne prawego górnego róg zdjęcia. Dla rekina kod będzie wyglądał tak:

rysuj2d.drawImage(rekin, polozenie_rekina_x,polozenie_rekina_y);

Użyte zmienne omówiliśmy wcześniej:

  • rekin,
  • polozenie_rekina_x,
  • polozenie_rekina_y

Umieśćmy cały kod w funkcji:

function rysuj_rekina()
{
rysuj2d.drawImage(rekin, polozenie_rekina_x,polozenie_rekina_y);
}

Zwróć uwagę, że jeszcze nic uruchomiliśmy (wywołaliśmy) kodu „rysuj_rekina„. Żeby to zrobić musimy użyć kodu „rysuj_rekina()„, ale zrobimy to później. Wpierw stwórzmy funkcję rysujące ocean i rybkę:

function rysuj_ocean()
{
rysuj2d.drawImage(ocean, 0,0);
}

Dlaczego ocean jest w punkcie 0 i 0? Jest to tło całej gry, które zaczyna się w prawym górnym rogu gry.

W przypadku rybki, wiemy z poprzednich części tej lekcji, że wysokość prawego górnego zdjęcia rybki zawsze będzie w punkcie: 290 (współrzędna y):

function rysuj_rybke()
{
rysuj2d.drawImage(rybka, 290, polozenie_rybki);
}

Wysokość (współrzędna y) będzie ulegać zmianie, dlatego musi być zmienną („polozenie_rybki„).

Jak uruchomić grę?

Stwórzmy najpierw funkcję dla naszego mechanizmu uruchamiającego grę:

function uruchom_gre()
{
       if(stan_gry==2)   
        {
        WYŁĄCZ GRĘ
        }
       else
        {
        URUCHOM GRĘ
        }
}

Zwróć uwagę, że do funkcji dodaliśmy instrukcję sterującą („if i else”). Jeśli zmienna „stan_gry” zmieni się na „2” to znaczy, że gra się zakończyła i trzeba ją wyłączyć. Jeśli zmienna ma inną liczbę to rysujemy grę.

Przed narysowaniem czegokolwiek na ekranie gry musimy go wyczyścić. Dlaczego go czyścimy? Odpowiedź znajdziesz w pierwszej części lekcji. Do czyszczenia ekranu gry służy metoda „clearRect” (ang. słowo „clear” oznacza czysty, a „rect” to skrót od słowa „rectangle” – prostokąt). Musimy podać jaki obszar chcemy wyczyścić, dlatego musimy podać:

  • współrzędną dla prawego górnego rogu ekranu gry (szerokość i wysokość);
  • współrzędną dla lewego dolnego rogu ekranu gry (szerokość i wysokość).

Kod do czyszczenia ekranu gry wygląda następująco:

rysuj2d.clearRect(0,0,700,700);

Prawy górny róg jest w punktach 0,0, a lewy dolny róg w punktach 700,700 (szerokość i wysokość płótna).

Narysujmy teraz ocean i rybkę (wywołajmy funkcję):

rysuj_ocean();
rysuj_rybke();   

Sprawdźmy czy rekin złapał rybkę (wywołajmy funkcję „wykryj_kolizje();„). Dodajmy kod poruszający rekina „poruszaj_rekinem()”, w nim zawarty jest kod rysujący rekina "rysuj_rekina()":

rysuj2d.clearRect(0,0,700,700);
wykryj_kolizje();
rysuj_ocean();
rysuj_rybke();   
poruszaj_rekinem(); 

Zwróć uwagę, że z grafiki pierwszy musi być wyświetlony ocean. To on jest tłem gry (więcej w pierwszej lekcji). Kolejność uruchomienia (wywołania) funkcji ma znaczenie, gdybyśmy wpierw uruchomili kod rysujący rybkę, a później ocean to nie zobaczylibyśmy rybki. Ocean przysłoniłby narysowaną wcześniej rybkę:

rysuj_rybke();
rysuj_ocean();

Koniec gry

Po zakończeniu gry wyświetlimy na środku ekranu (współrzędne 250, 250) napis: „<MNIAM MNIAM>” (rekin zjadł rybkę). Tekst będzie duży (35px), a użyty font to „Verdana”.

rysuj2d.font="35px Verdana";
rysuj2d.fillText("<MNIAM MNIAM>!!!", 250, 250);
clearInterval();

Metoda „rysuj2d.font” pozwala nam wybrać wielkość i rodzaj fonta („35px Verdana„) tekstu, który napiszemy na ekranie gry. Do umieszczenia napisu użyjemy metody „rysuj2d.fillText„, musimy tutaj podać tekst i współrzędne tekstu (x i y). 

Najważniejszy element to „clearInterval()„, bo służy do zatrzymania animacji gry.  Blokuje on ponowne uruchamianie funkcji „uruchom_gre” (czyli kodu: „setInterval(uruchom_gre, 100);„).

Cały kod:

function uruchom_gre()
{
if(stan_gry==2)   
  {
  rysuj2d.font="35px Verdana";
  rysuj2d.fillText("<MNIAM MNIAM>!!!", 250, 250);
  clearInterval();
  }
 
else
  {
     rysuj2d.clearRect(0,0,700,700);
     wykryj_kolizje();
  rysuj_ocean();
  rysuj_rybke();   
  poruszaj_rekinem();   
  }
 }

Gdzie mogę zagrać w grę i zobaczyć cały kod gry?

Ściągnij całą grę na swój komputer lub zagraj w nią.

Cały kod gry:

<!DOCTYPE html>
<html lang="pl">
    <head>
        <meta charset="utf-8">
        <title>Gra rybka</title>

    </head>
     <body>

         <canvas id="tu_rysuj" width="700" height="700" style="border: 1px solid black;">
            Niestety Twoja przeglądarka nie obsługuje gier HTML 5. Zaktualizuj przeglądarkę internetową.
        </canvas>
        <script>

var polozenie_rekina_x=500;
var polozenie_rekina_y=250;
var polozenie_rybki=10; 
var stan_gry=0; 

var ocean=document.createElement('img');
ocean.src = 'ocean.png';
var rybka=document.createElement('img');
rybka.src = 'rybka.png';
var rekin=document.createElement('img');
rekin.src = 'rekin.png';

window.onload=function()
{
plotno=document.getElementById('tu_rysuj');
rysuj2d=plotno.getContext('2d');
window.addEventListener('keydown', poruszaj_rybka);
setInterval(uruchom_gre, 100);
}

function uruchom_gre()
{
if(stan_gry==2)   
  {
  rysuj2d.font="35px Verdana";
  rysuj2d.fillText("<MNIAM MNIAM>!!!", 250, 250);
  clearInterval();
  }
 
else
  {
   rysuj2d.clearRect(0,0,700,700);  
  wykryj_kolizje();
  rysuj_ocean();
  rysuj_rybke();   
  poruszaj_rekinem();   
  }
}

function wykryj_kolizje()
{

  if(polozenie_rekina_x>=290&&polozenie_rekina_x<=370&&polozenie_rekina_y+52>=polozenie_rybki&&polozenie_rekina_y+52<=polozenie_rybki+51)
    {
    stan_gry=2;

    }
}

function rysuj_rybke()
{
rysuj2d.drawImage(rybka, 290, polozenie_rybki);
}
function rysuj_ocean()
{
rysuj2d.drawImage(ocean, 0,0);
}
function rysuj_rekina()
{
rysuj2d.drawImage(rekin, polozenie_rekina_x,polozenie_rekina_y);
}

function poruszaj_rekinem()
{
  if(polozenie_rekina_x<=-200)
  {
  polozenie_rekina_x=700;
  }
  else
  {
     if(polozenie_rekina_x>=700)
     {
     polozenie_rekina_x-=10;
     polozenie_rekina_y=Math.floor((Math.random() * 597) + 1);
     }
     else
     {
     polozenie_rekina_x-=10;
     rysuj_rekina();
     }
       }
}

function poruszaj_rybka(zdarzenie)
{           
klucz_klawisza = zdarzenie.keyCode;       
switch(klucz_klawisza)
   {
  
case 38:
  
if(polozenie_rybki<=0)
    
{
     polozenie_rybki=0;
     }
 
  else
   
  {
    
polozenie_rybki-=10;
    
}
  
break;
 
  case 40:
  
if(polozenie_rybki>=621)
    
{
    
polozenie_rybki=621;
   
  }
   else
    
{
    
polozenie_rybki+=10;
     }
  
break;
  
}

        </script>
    </body>
</html>

Podsumowanie

  1. O czym musisz wiedzieć zanim rozpoczniemy tworzyć grę?
    Lekcja jest dostosowana do osób dopiero uczących się tworzenia gier w przeglądarkach internetowych.
    Gra będzie działać w nowszych przeglądarkach internetowych. Lekcja
  2. Jak umieścić kod gry?
    Kod gry będzie stworzony w języku Javascript, dlatego do kodu strony internetowej należy znacznik otwierający <script> i znacznik zamykający </script>. Pomiędzy znacznikami umieszczamy kod gry.
  3. Co to jest zmienna, drzewo DOM, obiekt?
    Zmienna przypomina karton, który jest podpisany i zawiera coś, np.: karton telewizor ? zawiera tv, karton radio zawiera radio. Oto przykład zmiennej w języku Javascript: var karton_tv="telewizor";. Drzewo DOM to znaczniki języka HTML, które tworzą coś w rodzaju odwróconego drzewa:
    Znaczniki HTML tworzące odwrócone drzewo
    Obiekt

    Język Javascript opiera się na obiektach. Czym są te obiekty? Obiekty mogą przypominać rzeczy ze świata rzeczywistego, np. samochód.  Obiekty zawierają dużo informacji o sobie. Mają one zazwyczaj te informacje pogrupowane jako:

    • właściwości;
    • metody;
    • zdarzenia.
  4. Jak dodać obrazki?
    Przykładowe dodanie obrazka:

    var ocean=document.createElement('img');
    ocean.src = 'ocean.png';

  5. Jak  wprawić w ruch rekina  i wykryć krawędzie?
    Rekin wypływa z lewej krawędzi ekranu gry i kieruję się do prawej krawędzi. Należy stworzyć funkcję, która sprawdzi czy rekin wyszedł za prawą krawędź. W przypadku wyjścia poiwnien zostać przesunięty za lewą krawędź, gdzie zostanie wylosowana nowa wysokość na jakiej pojawi się rekin. Oto kod:
    function poruszaj_rekinem()
    {
      if(polozenie_rekina_x<=-200)
      {
      polozenie_rekina_x=700;
      }
      else
      {
         if(polozenie_rekina_x>=700)
         {
         polozenie_rekina_x-=10;
         polozenie_rekina_y=Math.floor((Math.random() * 597) + 1);
         }
         else
         {
         polozenie_rekina_x-=10;
         rysuj_rekina();
         }
           }
    }
  6. Jak sprawdzić czy rekin złapał rybkę?
    Rekin i rybka to prostokątne zdjęcia. Należy sprawdzić czy w czerwonym prostokącie znalazł się rekin (zielony punkt):
    Obrazek pokazuje ramkę wokół rybki i zielony punkt przy rekinie. Punkt ten jest z przodu rekina na połowie jego wysokości.

    function wykryj_kolizje()
      {

      if(polozenie_rekina_x>=290&&polozenie_rekina_x<=370&&polozenie_rekina_y+52>=polozenie_rybki&&polozenie_rekina_y+52<=polozenie_rybki+51)
        {
        stan_gry=2;

        }
      }

  7. Jak wprawić w ruch rybkę?
    Kod musi sprawdzić jaki klawisz został wciśnięty, a następnie na tej podstawie przesunąć rybkę. Wcześniej musi sprawdzić czy przesunięcie rybki nie będzie poza obszar gry.

    function poruszaj_rybka(zdarzenie)
    {           
    klucz_klawisza = zdarzenie.keyCode;       
    switch(klucz_klawisza)
       {
      
    case 38:
      
    if(polozenie_rybki<=0)
        
    {
         polozenie_rybki=0;
         }
     
      else
       
      {
        
    polozenie_rybki-=10;
        
    }
      
    break;
     
      case 40:
      
    if(polozenie_rybki>=621)
        
    {
        
    polozenie_rybki=621;
       
      }
       else
        
    {
        
    polozenie_rybki+=10;
         }
      
    break;
      
    }
    }      

  8. Jak sprawdzić jaki klawisz został wciśnięty po wczytaniu strony internetowej?

    Należy nasłuchiwać jaki klawisz został wciśnięty i przekazać to do funkcji „poruszaj_rybka”. Oto kod:

    window.onload=function()
    {
     window.addEventListener('keydown', poruszaj_rybka);
    }

  9. Jak wyświetlić (rysować) grę?

    Po wczytaniu okna mówimy przeglądarce internetowej, gdzie ma rysować („tu_rysuj”) i jak (2d). Dołączamy też nasłuchiwanie jaki klawisz został wciśnięty i uruchamiamy co 1/10 sekundy funkcję „uruchom_gre”.
    Oto kod:

    window.onload=function()
    {
    plotno=document.getElementById('tu_rysuj');
    rysuj2d=plotno.getContext('2d');
    window.addEventListener('keydown', poruszaj_rybka);
    setInterval(uruchom_gre, 100);
    }

    Następnie dodajemy funkcję rysującą, np.

    function rysuj_rybke()
    {
    rysuj2d.drawImage(rybka, 290, polozenie_rybki);
    }

  10. Jak uruchomić grę?

    Funkcja „uruchom_gre” sprawdza czy gra jest zakończona („stan_gry==2”). Jeśli nie jest zakończona to wywołuje funkcje odpowiedzialne za: czyszczenie ekranu gry, wykrywania kolizji, dodawania grafiki i poruszanie rekinem. Oto kod:

    function uruchom_gre()
    {
    if(stan_gry==2)   
      {
      rysuj2d.font="35px Verdana";
      rysuj2d.fillText("<MNIAM MNIAM>!!!", 250, 250);
      clearInterval();
      }
     
    else
      {
         rysuj2d.clearRect(0,0,700,700);
         wykryj_kolizje();
      rysuj_ocean();
      rysuj_rybke();   
      poruszaj_rekinem();   
      }
     }

  11. Gdzie mogę zagrać w grę i zobaczyć cały kod gry?
    Kod gry jest dostępny na tej stronie, a w grę możesz zagrać pod tym linkiem.
  • Podziel się na:

Zobacz również:

Dodaj komentarz

Twój adres email nie zostanie opublikowany. Pola, których wypełnienie jest wymagane, są oznaczone symbolem *