Skocz do zawartości
  • 👋 Witaj na MPCForum!

    Przeglądasz forum jako gość, co oznacza, że wiele świetnych funkcji jest jeszcze przed Tobą! 😎

    • Pełny dostęp do działów i ukrytych treści
    • Możliwość pisania i odpowiadania w tematach
    • System prywatnych wiadomości
    • Zbieranie reputacji i rozwijanie swojego profilu
    • Członkostwo w jednej z największych społeczności graczy

    👉 Dołączenie zajmie Ci mniej niż minutę – a zyskasz znacznie więcej!

    Zarejestruj się teraz

[TuT] Podstawa tworzenia gier (pętla główna) + Prosta animacja


Rekomendowane odpowiedzi

Opublikowano
Wiele początkujących osób nie rozumie w jaki sposób działają gry komputerowe. W tym wpisie przedstawię najważniejszą rzecz jaka jest potrzebna w każdej dynamicznej grze komputerowej na przykładzie języka JavaScript.
W JavaScript gry pisze się podobnie jak w każdym innym języku. Należy jednak pamiętać, że dynamiczne gry 2D lub 3D to zupełnie coś innego niż typowe gry viawww napisane w PHP (np. dosyć popularne "klikanki").
 
Chcąc napisać grę trzeba wiedzieć, że podstawą każdej gry jest pętla główna. Jest to zazwyczaj nieskończona pętla, która z każdym swoim przebiegiem wykonuje bardzo ważne rzeczy:
  • Czyści ekran
  • Wykonuje niezbędne operacje
  • Rysuje ponownie wszystkie elementy na ekranie
 
Do czego jest potrzebna pętla główna gry? Dynamiczne gry wymagają częstej aktualizacji elementów. Nie ma innego sposobu niż przerysowanie całej gry od nowa. Aby obraz na ekranie był płynny funkcja rysująca musi być wykonywana w tak krótkich odstępach czasu, by ludzkie oko nie było w stanie zaobserwować momentu odświeżania ekranu.
 
W językach takich jak C++ pętla główna może wyglądać następująco:
while(true) {
    // instrukcje
}
lub
for(; {
    // instrukcje
}
Niestety w JavaScript takie pętle będą powodować problemy, np. zawieszenie się przeglądarki i bardzo duże zużycie zasobów procesora. Dlatego w tym języku nieskończoną pętlę główną stosuje się trochę inaczej. Głównym elementem jest tutaj funkcja, która będzie wykonywana w kółko określoną ilość razy na sekundę. Taki efekt można uzyskać trzema sposobami. Do tej pory dwoma popularnymi sposobami było użycie timerów setTimeout() oraz setInterval(). Od niedawna jednak zalecane jest użycie funkcji requestAnimationFrame(), która jest specjalnie przeznaczona do ciągłego wykonywania danej funkcji.
 
Przedstawię teraz wszystkie trzy sposoby.
 
1. Timer setInterval()
 
Zaczniemy od funkcji setInterval(). Instrukcja ta w pierwszym parametrze przyjmuje nazwę funkcji, która ma być wykonywana, a w drugim czas w milisekundach co jaki ma się ta funkcja wykonywać.
function draw() {
    // czyszczenie ekranu
    // rysowanie gry
}
 
setInterval(draw, 1000/60);
W powyższym przykładzie ustaliliśmy, że funkcja draw() ma się wykonywać 60 razy na sekundę. Jest to optymalny czas, w którym animacja elementów (np. ich przesuwanie) będzie płynna.
 
2. Timer setTimeout()
 
Funkcja setTimeout() jest podobna do poprzedniej, ale wykona podaną instrukcję tylko jeden raz po określonym czasie. Aby uzyskać efekt jak poprzednio musimy wywołać ten timer na końcu funkcji draw(). Będzie to wyglądało w następujący sposób:
function draw() {
    // czyszczenie ekranu
    // rysowanie gry
   setTimeout(draw, 1000/60);
}
 
draw();
Jest to działanie nazywane rekurencją, czyli wywołanie funkcji wewnątrz tej samej funkcji.
 
3. Funkcja requestAnimationFrame()
 
Ta funkcja została przewidziana specjalnie do celu, który chcemy osiągnąć. Funkcję draw() również będziemy wywoływać rekurencyjnie, ale używając do tego funkcji requestAnimationFrame(). Tutaj już nie musimy ustalać czasu. Funkcja rysująca będzie wykonywała się w jak najbardziej optymalny sposób. 
function draw() {
    // czyszczenie ekranu
    // rysowanie gry
   window.requestAnimationFrame(draw);
}
 
window.requestAnimationFrame(draw);
 
Na przykładzie prostej animacji w Canvas pokażę jak działa pętla główna. Przypuśćmy, że chcemy zrobić animację obracającego się prostokąta.
 

 

  • Gdyby pętla nie działała to animacja nie wykonywała by się. 
 
 
  • Co się stanie gdy nie wyczyścimy ekranu przed ponownym przerysowaniem obrazu? 
 
 
  • Co jeśli liczba klatek animacji będzie zbyt niska, np. 10 razy na sekundę? 
 
 
  • Lub chociażby 25 razy na sekundę? 
 
 
  • Najbardziej optymalny czas to 60 razy na sekundę. 
 
 
  • Zastosowanie funkcji requestAnimationFrame() da jeszcze lepszy wynik. 
 
Kod końcowy:
var c = document.getElementById("myGame"); // pobranie elementu Canvas
var ctx = c.getContext("2d");
ctx.fillStyle = "#FF0000";
var width = c.width;
var height = c.height;
 
function draw() {
    ctx.clearRect(0, 0, c.width, c.height); // wyczyszczenie ekranu
 
   // instrukcje odpowiedzialne za poprawne narysowanie i animację obiektu
    ctx.translate(width/2-40, height/2-40);
    ctx.rotate(Math.PI / 180); 
    ctx.translate(-width/2+40, -height/2+40); 
    ctx.fillRect(width/4, height/4, width/2-80, height/2-80); 
 
    window.requestAnimationFrame(draw); // rekurencyjne wywołanie funkcji rysującej
}
 
window.requestAnimationFrame(draw); // rozpoczęcie głównej pętli gry
 
Myślę, że istnienie w grach tak ważnej rzeczy jak pętla główna zostało wyjaśnione przeze mnie w sposób dość zrozumiały dla osób początkujących. Jeśli interesują was poradniki związane z tworzeniem gier proszę o propozycję tematów, które mógłbym przedstawić.
 
Oryginał powyższego poradnika pochodzi z:

gamedevmania.com

  • 5 tygodni później...

Zarchiwizowany

Ten temat przebywa obecnie w archiwum. Dodawanie nowych odpowiedzi zostało zablokowane.

×
×
  • Dodaj nową pozycję...