Postanowiłem przetestować dziś możliwości JavaScript i nowego obiektu w HTML mianowicie Canvas. Moim celem było napisanie prostej gry kołko krzyżyk, którą zapewne dobrze znacie i kojarzycie.
Canvas jest to nowy element w języku HTML5, który umożliwa rysowanie grafiki 2D oraz 3D w locie(przez skryptowanie).
Na początku potrzebowałem kodu html. Jest to standardowy dokument html, który posiada w body element canvas
<!DOCTYPE html> <html> <head> <title>Kołko krzyżyk</title> <script src="//code.jquery.com/jquery-1.11.0.min.js"></script> <script> //tutaj bedzie skrypt </script> </head> <body> <canvas id="game" width="300" height="300" style="border:1px solid #d3d3d3;"></canvas> </body> </html>
Następnie zacząłem pisać potrzebne funkcje i zmienne. Pierwszą zmienną, którą zadeklarowałem jest zmienna move reprezentująca ilość ruchów, zmienna ta jest losowana po to by czasem zaczynało kółko, a czasem krzyżyk. Użyłem również funkcji, którą znalazłem w Internecie do podawania współrzędnych myszki, gdy użytkownik kliknie na obiekt Canvas:
var move = Math.floor((Math.random() * 10) + 1)%2; var gameFields = [0, 0, 0 ,0, 0, 0, 0, 0, 0]; function relMouseCoords(event) { var totalOffsetX = 0; var totalOffsetY = 0; var canvasX = 0; var canvasY = 0; var currentElement = this; do{ totalOffsetX += currentElement.offsetLeft - currentElement.scrollLeft; totalOffsetY += currentElement.offsetTop - currentElement.scrollTop; } while(currentElement = currentElement.offsetParent) canvasX = event.pageX - totalOffsetX; canvasY = event.pageY - totalOffsetY; return {x:canvasX, y:canvasY} } HTMLCanvasElement.prototype.relMouseCoords = relMouseCoords;
Teraz potrzebowałem linii reprezentujących siatkę gry, wykorzystałem do tego metody:
- lineTo(x,y) – definiuje linie od punktu x do y
- moveTo(x,y) – przenosi ścieżkę do określonego punktu bez rysowania
- clearRect(x,y,x1,y1) – czyści obszar od punktu x,y do x1, y1
- getContext(’2d’) – pobiera obszar do rysowania w canvas
- stroke() – rysuje zdefiniowane wcześniej linie(ścieżki)
function drawMap() { var ctx = document.getElementById("game").getContext("2d"); ctx.clearRect(0, 0, 300, 300); ctx.beginPath(); ctx.moveTo(100,0); ctx.lineTo(100,300); ctx.moveTo(200,0); ctx.lineTo(200,300); ctx.moveTo(0,100); ctx.lineTo(300,100); ctx.moveTo(0,200); ctx.lineTo(300,200); ctx.stroke(); }
Następnie potrzebowałem funkcji, która sprawdzi jakie pola są uzupełnione i narysuje kółko lub krzyżyk w tym miejscu.
function drawMoves() { var ctx= document.getElementById("game").getContext("2d"); ctx.font="60px Georgia"; var moveX = 100; var moveY = 70; for(i = 0 ; i <=8; i++) { if(i > 5) moveY = 100; else if (i > 2) moveY = 200; else moveY = 0; var fill = ''; if(gameFields[i] == 1) fill = 'X'; else if(gameFields[i] == 2) fill = 'O'; else fill = ''; ctx.fillText(fill, 25 + i % 3 * moveX, 70 + moveY); } }
Funkcja fillText(text, x, y) rysuje tekst w miejscu x,y.
Kolejną rzeczą, którą potrzebowałem jest funkcja sprawdzająca, w którym miejscu gracz kliknął i zapisująca ruch. Funkcja również sprawdza czy dozwolona liczba ruchów nie przekroczyła 9 oraz wywołuje funkcje sprawdzającą czy gra nie jest już wygrana.
function canvasClicked() { var cords = document.getElementById("game").relMouseCoords(event); move++; if(move > 9) { endGame(); return; } if(cords.x < 100 && cords.y < 100) gameFields[0] = move % 2 == 1 ? 1 : 2; else if(cords.x>100 && cords.x <= 200 && cords.y < 100) gameFields[1] = move % 2 == 1 ? 1 : 2; else if(cords.x>200 && cords.x <= 300 && cords.y < 100) gameFields[2] = move % 2 == 1 ? 1 : 2; else if(cords.x < 100 && cords.y < 200 && cords.y > 100) gameFields[6] = move % 2 == 1 ? 1 : 2; else if(cords.x>100 && cords.x <= 200 && cords.y < 200 && cords.y > 100) gameFields[7] = move % 2 == 1 ? 1 : 2; else if(cords.x>200 && cords.x <= 300 && cords.y < 200 && cords.y > 100) gameFields[8] = move % 2 == 1 ? 1 : 2; else if(cords.x < 100 && cords.y < 300 && cords.y > 200) gameFields[3] = move % 2 == 1 ? 1 : 2; else if(cords.x>100 && cords.x <= 200 && cords.y < 300 && cords.y > 200) gameFields[4] = move % 2 == 1 ? 1 : 2; else if(cords.x>200 && cords.x <= 300 && cords.y < 300 && cords.y > 200) gameFields[5] = move % 2 == 1 ? 1 : 2; if(check(1)) { alert('X wygrywa'); endGame(); return; } else if(check(2)) { alert('O wygrywa'); endGame(); return; } drawMoves(); }
Ostatnie dwie funkcje potrzebne do gry to funkcja endGame() kończąca gre oraz check() sprawdzająca czy kółko lub krzyżyk nie wygrało gry.
function endGame() { move = 0; gameFields = [0, 0, 0 ,0, 0, 0, 0, 0, 0]; drawMap(); } function check(x) { if((gameFields[0] == x && gameFields[1] == x && gameFields[2] == x) || (gameFields[3] == x && gameFields[4] == x && gameFields[5] == x) || (gameFields[6] == x && gameFields[7] == x && gameFields[8] == x)) { return true; } if((gameFields[0] == x && gameFields[3] == x && gameFields[6] == x) || (gameFields[1] == x && gameFields[4] == x && gameFields[7] == x) || (gameFields[2] == x && gameFields[5] == x && gameFields[8] == x)) { return true; } if((gameFields[0] == x && gameFields[5] == x && gameFields[7] == x) || (gameFields[2] == x && gameFields[3] == x && gameFields[7] == x)) { return true; } }
Gdy już to mamy, możemy uruchomić grę
$(function (){ $("#game").click(canvasClicked); drawMap(); drawMoves(); });
Użyłem do tego funkcji JQuery document.ready() ale równie dobrze można to zrobić bez JQuery, używając standardowych funkcji JavaScript.
I to tyle. Działający kod możecie zobaczyć pod adresem http://blog.rpodwika.pl/game.html
Gra nie jest jeszcze w pełni ukończona, ale znalezienie błędów pozostawiam Wam. Są co najmniej 3, o których wiem.
Dzięki za przeczytanie artykułu i polecam korzystać z Canvas, gdyż Flash odchodzi do lamusa i nie będzie rozwijany przez Adobe.
Jak to odpalić? I gdzie umieścić, bo żeś tego nie napisał.
kod js wrzucasz zamiast lini „// tam gdzie będzie skrypt” w kodzie html
programuje 30 lat i ten kod mi się podoba