HTML5: Zabawa z canvas – odbijające się kulki

Już prawie jesień a na dworze cały czas upały. Mimo, że atmosfera nie sprzyja pracy, najwyższy czas na kolejny wpis. Tym razem krótka notka o tworze, który powstał w wyniku zabawy z canvas, elementem graficznym HTML5.

Oto Kulki.

kulki canvas

Jest to bardzo prosty skrypt, wykorzystujący możliwości elementu HTML5 canvas. Dzięki temu elementowi, można tworzyć grafikę w przeglądarce. Gdy doda się do tego javascriptowe setInterval i mamy piękną animowaną grafikę.

Jak to działa? Już tłumaczę. Najpierw muszę pobrać kontekst elementu canvas:

Potrzebny jest, aby móc rysować po canvasie.

Następnie tworzę klasę piłki – Ball. wygląda to tak:

Konstruktor klasy, przyjmuje dwa argumenty, x i y. Będą to współrzędne, na w których znajdować będzie się punkt środkowy naszych kulek.

To jedyne parametry, ustalone przeze mnie. Reszta jest generowana losowo. Potrzebuję do tego odpowiedniej funkcji. Zajmuje się tym pierwsza metoda klasy Ball. Metoda ta przyjmuje dwa argumenty. Jest to zakres z pomiędzy którego, wybierana będzie losowa wartość.

Następna metoda randomize. Losuje wartości dla pól radius, speedx oraz speedy. radius określać będzie promień piłki, a dwa kolejne pola jej prędkość poziomą i pionową.

Trzy kolejne metody reverseSpeedX, reverseSpeedY oraz updatePosition manipulują polami odpowiadającymi za prędkość piłki oraz jej położenie. Wytłumaczę dokładnie o co chodzi, gdy dojdziemy do rysowania po canvas.

Dalsza część kodu to wywołanie trzech instancji klasy Ball oraz ustawienie im odpowiednich pól metodą randomize. Dzięki temu, piłki będą zawsze różnej wielkości i będą poruszać się z różnymi prędkościami oraz pod różnymi kątami.

Wszystkie piłki wrzucam do tablicy balls, bo tak będzie mi wygodniej 🙂

A teraz zaczyna się zabawa czyli setInterval

setInterval to bardzo prosta w działaniu funkcja. Wywołuje ona funkcję o nazwie podanej jako pierwszy argument co liczbę milisekund podaną jako drugi argument. Czyli 1000 w drugim argumencie oznacza wywołanie funkcji co sekundę. W tym wypadku wywołuję funkcję animate co jedną dwudziestą sekundy.

Zanim przejdę dalej, muszę objaśnić parę spraw o canvas oraz dwóch metodach dwuwymairowego kontekstu: clearRect oraz arc. Canvas jest jak układ współrzędnych. 0,0 odnosi się do lewego górnego wierzchołka. 10, 10 to punkt leżący 10 pikseli w prawo i 10 pikseli w dół od lewego górnego wierzchołka. Działa to bardzo podobnie jak ustawianie elementów html pozycjonowanych absolutnie w css, właściwościami left oraz top.

Co do metod, najpierw przykłady użycia:

pierwsza metodaclearRect używana jest do czyszczenie elementu canvas. Przyjmuje 4 argumenty. pierwsze dwa to współrzędne lewego, górnego wierzchołka prostokątnego pola, które zostanie wyczyszczone. Dwa kolejne to długość i szerokość tego prostokąta. Nasz przykład czyści całą powierzchnie elementu canvas.

Kolejna metoda, arc, używana jest do rysowania łuku na elemencie canvas. Przyjmuje ona 5 argumentów. dwa pierwsze to współrzędne, w których znajdować będzie się środek rysowanego łuku (wyobraźcie sobie, że do narysowania łuku używacie cyrkla. Punkt, oznaczony przez dwa pierwsze argumenty, to punkt w który wbijacie cyrkiel). W tym wypadku, będą to x i y instancji klasy ball. Kolejny argument to promień użyty do narysowania okręgu (jak szeroko rozłożycie cyrkiel). czwarty argument to kąt rysowanego łuku (jak długo będziecie rysować cyrklem). Ten argument jest wyjątkowy ponieważ podajemy go w radianach. Na szczęście wystarczy wiedzieć że PI daje nam pół okręgu. Ja chcę narysować cały okrąg więc, podaję wartość podwojonego PI. Ostatni argument to kierunek rysowania łuku, true – zgodnie z ruchem wskazówek zegara, false – przeciwnie. Dla mnie i tak nie ma to znaczenia, ponieważ rysuję łuk o 360 stopniach, czyli okrąg 🙂

Skoro to jest już jasne, mogę przejść dalej, czyli do funkcji animate, serca mojego programu. Założenie jest proste. Co jedną dwudziestą sekundy, funkcja ta robi następujące rzeczy:

  • czyści element canvas,
  • sprawdza czy piłka nie wpadła na ściane, jeśli tak, odwraca wartość odpowiednio speedx lub speedy
  • wywołuje metodę updatePosition instancji ball, która uaktualnia, pola x oraz y, o wartości pól speedx oraz speedy,
  • rysuje piłkę

Wynikiem tego jest wyświetlenie wielu nieznacznie różnych obrazów w bardzo krótkim odstępie czasu, czyli animacja 🙂 każde nowe wywołanie funkcji animate, jest jakby wyświetleniem jednej klatki animacji. Na każdej klatce piłka jest kawałek dalej.

A tak wygląda kod:

Najpierw czyszczony jest canvas, dzięki temu za każdym wywołaniem animate piłka (a w zasadzie piłki) rysowane są na czystym polu. Ponieważ mam 3 instancje klasy Ball, to co dzieje się dalej wykonuje dla każdej z nich, iterując pętlą for, przez tablice, która je składuje.

najpierw sprawdzam czy piłka nie wyszła poza lewą lub prawą krawędź elementu canvas, jeśli tak się stało odwracam wartość speedx. W praktyce oznacza to, że jeśli piłka dotrze do prawej krawędzi wartość speedx, która do tej pory powodowała, że współrzędna x piłki rosła, teraz będzie ujemna, a co za tym idzie, wartość x będzie się zmniejszać. Jeśli piłka dotrze do lewej krawędzi, wartość speedx zacznie rosnąć. I tak do znudzenia 🙂

To samo dzieje się w przypadku wartość speedy, tym razem jednak chodzi o krawędzie górną i dolną. Ta prosta sztuczka, powoduje, że piłki zdają się odbijać od krawędzi elementu canvas.

Gdy to jest już załatwione, funkcja animate wywołuje metode updatePosition, czyli wartość x oraz y modyfikowane są o wartości odpowiednio speedx oraz speedy.

Zostało tylko narysowanie piłki. Zawsze kiedy zaczyna się rysować coś na canvasie należy wywołać metodę beginPath, a kiedy kończy, metodę closePath obiektu ctx. Metoda arc jest już znana, rysuje one okrąg, natomiast metoda fill wypełnia ten okrąg kolorem. Domyślnie, jest to czarny.

I to wszystko. Ten prosty skrypt daje mi już dość zaawansowany efekt animacji. Od tego miejsca już prosta droga, do gier typu pong czy breakout 🙂

Dodaj komentarz

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