W rozdziale:
- Wprowadzenie
- Rysowanie prostych kształtów
- Współrzędne na kanwie
- Ścieżki na kanwie
- Rysowanie gradientów
- Rysowanie tekstu na kanwie
- Wyświetlanie obrazów na kanwie
- Kanwa w Internet Explorerze
- Przykładowa gra
Kompletny realny przykład — gra Halma
Halma to bardzo stara gra planszowa. Istnieje wiele jej odmian. Ten przykład dotyczy wersji dla jednego gracza z planszą o wymiarach 9 × 9 pól. Na początku gry pionki są ustawione w kwadrat 3 × 3 w lewym dolnym rogu planszy. Celem gracza jest przeniesienie tego kwadratu do prawgo górnego rogu przy użyciu jak najmniejszej liczby ruchów.
W grze Halma dozwolone są dwa rodzaje ruchu:
- przesunięcie pionka w dowolnym kierunku na sąsiednie puste pole. Puste pole to takie, na którym aktualnie nie znajduje się żaden pionek. Sąsiednie pole to pole znajdujące się na lewo, prawo, nad, pod lub po skosie względem aktualnego pola. (Nie ma możliwości wychodzenia poza krawędź planszy, tzn. jeśli pionek znajduje się przy lewej krawędzi, to nie można go przesunąć w lewo, a jeśli pionek znajduje się przy dolnej krawędzi, to nie można go przesunąć w dół).
- Pionki mogą też przeskakiwać inne pionki i można to robić seriami. To znaczy, że można przeskoczyć jeden sąsiedni pionek, a po nim następny i liczy się to jako jeden ruch. Taki seryjny skok liczy się jako jeden ruch, bez względu na liczbę przeskoczonych w nim pionków. (Jako że celem gry jest przeniesienie pionków na drugą stronę planszy przy użyciu jak najmniejszej liczby ruchów, najlepszą strategią jest konstruowanie długich łańcuchów zajmujących co drugie pole pionków, aby potem je przeskoczyć innymi pionkami).
Oto plansza gry. Możesz w nią zagrać na osobnej stronie, jeśli chcesz przy okazji pobadać ją narzędziami dla webmasterów.
Jak to działa? Cieszę się, że pytasz. Nie będę tu pokazywał całego kodu, bo można go obejrzeć w pliku halma.js. Skoncentruję się tylko na części kodu dotyczącej rysowania na kanwie i reagowania na kliknięcia.
Gra jest inicjowana podczas ładowania strony poprzez ustawienie wymiarów elementu <canvas> i zapisanie referencji do jego kontekstu rysunkowego.
gCanvasElement.width = kPixelWidth;
gCanvasElement.height = kPixelHeight;
gDrawingContext = gCanvasElement.getContext("2d");
Potem robione jest coś, o czym jescze nie pisałem: do elementu <canvas> dodawana jest procedura nasłuchu zdarzeń kliknięcia myszą.
gCanvasElement.addEventListener("click", halmaOnClick, false);
Funkcja halmaOnClick() jest wywoływana, gdy użytkownik kliknie gdziekolwiek w obrębie kanwy. Jej argumentem jest obiekt MouseEvent zawierający informacje o miejscu, w którym nastąpiło kliknięcie.
function halmaOnClick(e) {
var cell = getCursorPosition(e);
// Reszta kodu to logika gry HTML5
for (var i = 0; i < gNumPieces; i++) {
if ((gPieces[i].row == cell.row) &&
(gPieces[i].column == cell.column)) {
clickOnPiece(i);
return;
}
}
clickOnEmptyCell(cell);
}
Kolejną czynnością jest pobranie obiektu MouseEvent i obliczenie, który kwadrat na planszy został kliknięty. Jako że plansza zajmuje cały obszar kanwy, każde kliknięcie jest gdzieś na niej. Musimy tylko dowiedzieć się gdzie. Jest to trudne ze względu na to, że zdarzenia myszy w każdej przeglądarce są zaimplementowane nieco inaczej.
function getCursorPosition(e) {
var x;
var y;
if (e.pageX != undefined && e.pageY != undefined) {
x = e.pageX;
y = e.pageY;
}
else {
x = e.clientX + document.body.scrollLeft +
document.documentElement.scrollLeft;
y = e.clientY + document.body.scrollTop +
document.documentElement.scrollTop;
}
Teraz mamy współrzędne x i y względne w odniesieniu do dokumentu (czyli całej strony HTML). Na razie niewiele mamy z nich pożytku. Potrzebujemy współrzędnych względnych w odniesieniu do kanwy.
x -= gCanvasElement.offsetLeft;
y -= gCanvasElement.offsetTop;
Teraz mamy już współrzędne x i y względne w odniesieniu do kanwy. To znaczy, jeśli w tym momencie wartości x i y wynoszą 0, wiemy, że użytkownik kliknął piksel znajdujący się w lewym górnym rogu kanwy.
Dzięki tym informacjom możemy obliczyć, który kwadrat planszy został kliknięty i odpowiednio na to zareagować.
var cell = new Cell(Math.floor(y/kPieceHeight),
Math.floor(x/kPieceWidth));
return cell;
}
Uff! Zdarzenia myszy to rzecz dla prawdziwych twardzieli. Ale teraz już tego samego kodu możesz użyć we wszystkich swoich aplikacjach. Zapamiętaj: kliknięcie myszą → współrzędne dokumentu → współrzędne kanwy → logika aplikacji.
Teraz przyjrzymy się głównej procedurze rysującej. Jako że grafika jest w tym przypadku bardzo prosta, postanowiłem, że za każdym razem gdy coś się mzienia na planszy rysować ją od nowa w całości. Nie jest to konieczne. Kontekst rysunkowy kanwy zachowa wszystko, co zostały w nim narysowane, nawet gdy użytkownik przewinie stronę albo przejdzie na inną kartę w przeglądarce, a potem wróci do gry. Jeśli będziesz przy użyciu kanwy tworzyć aplikację o bardziej skomplikowanej grafice (np. grę arcade), możesz zoptymalizować jej działanie odświeżając tylko te obszary, w których coś się zmieniło. Ale to nie jest tematem tego podręcznika.
gDrawingContext.clearRect(0, 0, kPixelWidth, kPixelHeight);
Procedura rysująca planszę powinna wyglądać znajomo. Jest podobna do układu współrzędnych kanwy, który narysowaliśmy wcześniej.
gDrawingContext.beginPath();
/* pionowe linie */
for (var x = 0; x <= kPixelWidth; x += kPieceWidth) {
gDrawingContext.moveTo(0.5 + x, 0);
gDrawingContext.lineTo(0.5 + x, kPixelHeight);
}
/* poziome linie */
for (var y = 0; y <= kPixelHeight; y += kPieceHeight) {
gDrawingContext.moveTo(0, 0.5 + y);
gDrawingContext.lineTo(kPixelWidth, 0.5 + y);
}
/* Rysowanie! */
gDrawingContext.strokeStyle = "#ccc";
gDrawingContext.stroke();
Najlepsza zabawa jest przy rysowaniu pionków. W tej grze pionki są okrągłe, a my jeszcze nie wiemy, jak rysować koła. Ponadto, gdy użytkownik kliknie pionek z zamiarem przesunięcia go na inne miejsce, tło tego pionka powinno się zabarwić. W poniższym kodzie argument p reprezentuje pionek, który ma własności row i column określające jego bieżące położenie na planszy. Przy użyciu kilku stałych gry zamieniamy współrzdne (column, row) na współrzędne (x, y) kanwy, potem rysujemy koło, a później (jeśli pionek jest kliknięty) wypełniamy te koło jednolitym kolorem.
function drawPiece(p, selected) {
var column = p.column;
var row = p.row;
var x = (column * kPieceWidth) + (kPieceWidth/2);
var y = (row * kPieceHeight) + (kPieceHeight/2);
var radius = (kPieceWidth/2) - (kPieceWidth/10);
To koniec logiki gry HTML5. Mamy już współrzędne (x, y) na kanwie środka koła, które chcemy narysować. W API kanwy nie ma metody o nazwie circle(), ale jest metoda arc(). Służy ona do tworzenia łuków, a czym jest okrąg, jak nie łukiem z połączonymi końcami? Pamiętasz podstawy geometrii? Metoda arc() jako argumenty pobiera współrzędne środka (x, y), promień, kąt początkowy i końcowy (w radianach) oraz kierunkowskaz (false oznacza w prawo, true oznacza w lewo). Do wykonywania obliczeń w radianach można wykorzystać moduł Math języka JavaScript.
gDrawingContext.beginPath();
gDrawingContext.arc(x, y, radius, 0, Math.PI * 2, false);
gDrawingContext.closePath();
Chwileczkę! Nic jeszcze nie zostało narysowane. Metoda arc() , podobnie jak moveTo() i lineTo, jest metodą „ołówkową”. Aby narysować koło, musimy ustawić własność strokeStyle i wywołać metodę stroke().
gDrawingContext.strokeStyle = "#000";
gDrawingContext.stroke();
A co z sytuacją, gdy pionek jest kliknięty? Można wykorzystać tę samą ścieżkę, co do narysowania obrysu pionka i wypełnić tworzony przez nią okrąg kolorem.
if (selected) {
gDrawingContext.fillStyle = "#000";
gDrawingContext.fill();
}
I to by było na tyle. Reszta programu to logika gry — rozróżnianie dozwolonych i niedozwolonych ruchów, liczenie liczby ruchów, sprawdzanie czy gry dobiegła końca itp. Użyliśmy elementu <canvas>, na którym narysowaliśmy 9 okręgów i kilka prostych kresek oraz zdefiniowaliśmy jedną procedurę obsługi zdarzenia onclick, aby utworzyć ciekawą planszową grę logiczną. Hurrra!
Lektura uzupełniająca
- Kurs posługiwania się kanwą w serwise Mozilla Developer Center
- HTML5
canvas— podstawy, Mihai Sucan - CanvasDemos.com: dema, narzędzia i kursy dotyczące używania elementu HTML
canvas - Element
canvaswe wstępnej wersji standardu HTML5 - Poradnik dla programistów zajmujących się przeglądarką Internet Explorer 9: element HTML5
canvas





Wysyłam...
Dodaj komentarz