salary 1319059 ml

Jak stworzyć grę internetową w Phaser (2/2)

Witam w drugiej części artykułu, w którym pokazuję jak z użyciem fameworku Phaser stworzyć prostą grę polegającą na zbieraniu gwiazdek kosmitą. W poprzedniej części przygotowaliśmy świat gry oraz dodaliśmy bohatera. Tym razem dokończymy naszą grę.

Dodajemy ruch bohatera

Aby dać naszemu bohaterowi możliwość ruchu musimy w jakiś sposób obsłużyć naciskanie przycisków przez gracza. Na szczęście Phaser ma wbudowaną obsługę przycisków, dzięki czemu możemy w bardzo prosty sposób wykrywać naciskanie przez gracza danych klawiszy.

Na początek musimy dodać poniższy kod do funkcji create:

1
cursor = game.input.keyboard.createCursorKeys();

Kod ten spowoduje utworzenie globalnego obiektu cursor, którego będziemy używać do wykrywania naciśnięcia przycisków.

Jak się pewnie domyślasz sprawdzanie, czy gracz wciska dany klawisz będzie się odbywać w ciele funkcji update, która jest uruchamiana w pętli. Na początek damy naszemu bohaterowi możliwość skakania, aby to zrobić dodaj poniższy fragment do funkcji update.

1
2
3
if (cursor.up.isDown && player.body.touching.down) {
  player.body.velocity.y = -350;
};

W tym kodzie sprawdzamy, czy przycisk „strzałka w górę” jest naciśnięty i czy dół obiektu player dotyka innego obiektu, jeśli oba warunki są spełnione, to następuje nadanie prędkości w górę obiektowi player.

Jeśli teraz uruchomisz grę i naciśniesz strzałkę w górę to mały kosmita podskoczy.

SCREEN_4

Kolejnym oczywistym krokiem jest danie zawodnikowi możliwości poruszania w prawo i w lewo. Aby to zrobić wstaw poniższy kod do funkcji update.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
if (cursor.left.isDown)
{
  player.body.velocity.x = -150;
  player.animations.play('left');
}
else if (cursor.right.isDown)
{
  player.body.velocity.x = 150;
  player.animations.play('right');
}
else
{
  player.body.velocity.x = 0;
  player.animations.stop();
  player.frame = 4;
};

Przeanalizujmy teraz dokładnie tą duża instrukcję if. Na początku sprawdzamy, czy przycisk „strzałka w lewo” jest naciśnięty, jeśli tak, to nadajemy obiektowi prędkość w lewo i uruchamiamy animację left. Gdy strzałka w lewo nie jest naciśnięta, to sprawdzamy naciśnięcie strzałki w prawo, jeśli ona jest wciśnięta, to nadajemy obiektowi prędkość w prawo i uruchamiamy animację rigth. Jeśli ani strzałka w lewo ani w prawo nie są naciśnięte, to zerujemy poziomą prędkość obiektu, zatrzymujemy animację i wyświetlamy klatkę numer 4, czyli tą na której kosmita jest skierowany w przód.

Na tym etapie Twój bohater ma już możliwość poruszania się w prawo/lewo oraz skakania, dzięki temu możesz już nim wskoczyć na utworzone wcześniej platformy.

SCREEN_5

Jeśli uważasz, że kosmita skacze za wysoko lub za nisko, czy też któraś z platform nie jest na właściwej wysokości możesz wszystko samodzielnie dostosować zmieniając odpowiednie wartości w kodzie gry.

Zbieramy gwiazdki

Nasz gra prezentuje się już całkiem dobrze, można chodzić i skakać kosmitą po platformach, brakuje w niej jednak jakiegoś celu, który by zachęcił potencjalnego gracza do spędzenia przy niej czasu. Przejdźmy więc do dodatnia gwiazdek, które będą spadać z nieba, a celem gracza będzie zbieranie ich.

Dodaj to funkcji create poniższy fragment:

1
2
3
4
5
6
7
8
9
stars = game.add.group();
stars.enableBody = true;

for (var i = 0; i < 20; i++) {
  var star = stars.create(i * 40, 0, 'star');

  star.body.gravity.y = 400;
  star.body.bounce.y = 0.7 + Math.random() * 0.3;
}; 

Myślę, że nie powinieneś mieć większych trudności ze zrozumieniem powyższego kodu, ponieważ widziałeś już większość instrukcji, które się w nim znajdują. Jednak dla rozwiania wszelkich wątpliwości krótko go objaśnię.

W pierwszej linii tworzymy pustą grupę obiektów, którą przypisujemy do zmiennej globalnej stars. Grupa ta będzie zawierać spadające gwiazdki. W kolejnej linii włączamy wykrywanie ciała gwiazdek przez system fizyki. Dalej znajduje się pętla for w której następuje tworzenie gwiazdek. W tym miejscu pojawia się nowy element, czyli atrybut star.body.bounce.y. Właściwość ta określa jak bardzo dany element ma się odbijać od podłoża na który spadnie. Wartością domyślną jest 0, które oznacza brak odbicia. Wartość 1 oznacza 100% odbicie, czyli obiekt odbije się na taką wysokość, z jakiej spada. Dzięki zastosowaniu metody Math.random() generującej losową liczbę pomiędzy 0 a 1, nasze gwiazdki będą posiadały atrybut star.body.bounce.y, z wartością w przedziale od 0.7 do 1.

Tworzenie gwiazdek mamy już gotowe, pora więc na przypisanie odpowiedniego zachowania to tych obiektów. Na początek dodaj poniższy kod do funkcji update:

1
2
game.physics.arcade.collide(stars, platforms);
game.physics.arcade.overlap(player, stars, collectStar);

Pierwsza linia nie jest niczym nowym, służy ona do wykrywania kolizji pomiędzy grupami stars i platforms, powoduje to, że gwiazdki nie nachodzą na platformy, tylko się od nich odbijają. Tej samej metody używaliśmy do wykrywania kolizji pomiędzy zawodnikiem a platformami.

W drugiej linii znajduje się metoda game.physics.arcade.overlap, której jeszcze nie miałeś okazji poznać. Metoda ta służy do sprawdzania, czy dwa obiekty na siebie nachodzą. W naszym przypadku przyjmuje ona 3 argumenty, pierwsze dwa to obiekty lub grupy obiektów, których nachodzenie na siebie ma być wykryte. Ostatni to nazwa funkcji, która ma zostać wykonana w momencie wykrycia nachodzenia na siebie danych obiektów. Podczas uruchomienia tej funkcji, zostaną do niej przekazane dwa obiekty, które na siebie naszły.

Pora teraz na dodanie samej funkcji collectStar. Dodaj poniży kod do bloku script, poza innymi funkcjami.

1
2
3
function collectStar (player, star) {
  star.kill();
};

Jak widzisz jedyne co robi powyższa funkcja to wykonanie metody kill na gwiazdce, na którą naszedł gracz. Metoda kill usuwa dany obiekt z obszaru gry.

W tym momencie testując naszą grę można już zbierać gwiazdki.

SCREEN_6

Dodajemy punkty

Jak wiadomo w prawie każdej grze znajduje się jakiś rodzaj zbierania punktów, nie inaczej będzie i u nas. W naszym przypadku liczenie zebranych gwiazdek nie ma większego sensu, ponieważ celem zawodnika jest zawsze zebranie wszystkich. Według mnie lepszym rozwiązaniem będzie liczenie czasu, w jakim zawodnik zebrał gwiazdki.

Na początek dodamy do naszej gry zwykły licznik odmierzający czas. Dodaj poniższy kod do funkcji create

1
2
3
counter = 0;
counterText = game.add.text(16, 16, 'Czas: 0', { fontSize: '32px', fill: '#000' });
game.time.events.loop(1000, updateCounter);

W pierwszej linii, tworzymy globalną zmienną counter, w niej będzie się znajdować odmierzony czas wyrażony w sekundach. Kolejna linia jest odpowiedzialna za dodanie tekstu licznika. Pierwsze dwa parametry to współrzędne X i Y wyświetlanego tekstu, kolejny argument to wyświetlany tekst, a ostatni to style tekstu, czyli w naszym przykładzie rozmiar czcionki oraz wypełnienie. Zwróć uwagę, że obiekt zwracany przez metodę game.add.text zostaje przypisany do globalnej zmiennej counterText. Odwołując się do tego obiektu z innych miejsc gry będziemy mogli zmieniać wyświetlany tekst.

Ostatnia linia dodaję pętlę, która co pewien czas będzie uruchamiać daną funkcję. Pierwszy argument to właśnie czas wyrażony w milisekundach, natomiast drugi parametr, to nazwa funkcji, która ma być uruchamiana.

Jak się pewnie domyślasz musimy teraz utworzyć funkcję updateCounter. Dodaj poniższy kod do bloku script, poza innymi funkcjami.

1
2
3
4
function updateCounter() {
  counter++;
  counterText.setText('Czas: ' + counter);
};

Funkcja ta po prostu zwiększa wartość licznika oraz używając metody setText na obiekcie counterText wyświetla nowy tekst licznika.

Jeśli teraz zagrasz w naszą grę zobaczysz już działający licznik

SCREEN_7

Musimy jeszcze wykryć moment, w którym gracz zbierze wszystkie gwiazdki, tak aby zatrzymać licznik. Dodaj do funkcji create poniższą linię:

1
colledtedStars = 0;

W tej zmiennej będziemy przechowywać ilość zebranych gwiazdek.

Teraz musimy jeszcze dodać kod do metody collectStar w która jest uruchamiana w momencie zebrania gwiazdki przez gracza.

1
2
3
4
5
colledtedStars++;
if (colledtedStars >= 20) {
  game.time.events.stop();
  counterText.setText('Twój czas: ' + counter + ' sekund');
};

Jak widzisz podczas zebrania danej gwiazdki zwiększamy zmienną colledtedStars zawierającą liczbę zebranych gwiazdek. Jeśli zebrano już wszystkie 20 gwiazdek, to metodą game.time.events.stop() zatrzymujemy pętlę odpowiedzialną za liczenie czasu oraz wyświetlamy tekst zawierający czas ukończenia gry.

SCREEN_8

Podsumowanie

W tym dwuczęściowym artykule pokazałem jak można przy pomocy Phaser’a stworzyć prostą grę, polegającą na zbieraniu gwiazdek. Zachęcam Cię jeszcze do rozbudowania tej gry, na pewno masz jakiś pomysł, który można wdrożyć. Możesz na przykład dodać dodatkowe platformy, albo pozwolić graczowi na szybsze spadanie po naciśnięciu strzałki w dół.

Ikony użyte podczas tworzenia gry oraz pomysł na grę pochodzą z oficjalnego tutoriala Phaser udostępnionego na licencji MIT na stronie https://github.com/photonstorm/phaser

Kurs wideo

Jeśli spodobał Ci się ten artykuł i chciałbyś dokładniej poznać narzędzie Phaser, serdecznie zapraszamy do naszego nowego kursu wideo Tworzenie gier w JavaScript. Tworzymy w nim klona popularnej gry Pacman, przy pomocy frameworku Phaser. Jeśli jeszcze nie masz konta, zarejestruj się za darmo.