CANVAS шаг за шагом:
В детстве у меня были пятнашки, я думаю все знают эту головоломку. Двигать пятнашки в пластиковой коробочке до получения заветного порядка цифр было очень интересным занятием. Вот и совсем недавно, в порядке спортивного интереса, я написал для себя пятнашки в которые бы можно было играть не только из окна браузера, но и с смартфона под управлением ОС Андроид или iOS.
Наша игра будет состоять из двух файлов лежащих в одной папочке, первый обзовём index.htm, а второй puzzle15.js
Содержимое html файла в течении всего поста меняться не будет, и собственно он должен выглядеть приблизительно так:
Написанием второго файла мы и будем заняты. Итак изначально мы напишем функцию init, которая изменит размер нашего холста и закрасит его однородым цветом, т.е. содержимое файла puzzle15.js должно быть таким:
Если открыть браузером файл index.htm, то можно увидеть тёмно-серый прямоугольник. Для пятнашек я заготовил один класс в который вынесена вся игровая логика, этот класс собственно надо поместить в файл:
Теперь нашу игру можно смело перевоплотить из статичного прямоугольника, в практически рабочие пятнашки
Ну вот осталось добавить лишь обработку событий мыши и касаний, и у нас получиться вполне рабочая версия пятнашек, для этого в функцию init после последней строки field.draw(context, cellSize) добавим немного кода:
Кто хочет сразу поиграть для того ссылка.
Ничего сложного в коде нет, и всё пишется очень быстро. Спасибо пользователю hobbeat за идею и фотографию пятнашек на айПоде.
В детстве у меня были пятнашки, я думаю все знают эту головоломку. Двигать пятнашки в пластиковой коробочке до получения заветного порядка цифр было очень интересным занятием. Вот и совсем недавно, в порядке спортивного интереса, я написал для себя пятнашки в которые бы можно было играть не только из окна браузера, но и с смартфона под управлением ОС Андроид или iOS.
Наша игра будет состоять из двух файлов лежащих в одной папочке, первый обзовём index.htm, а второй puzzle15.js
Содержимое html файла в течении всего поста меняться не будет, и собственно он должен выглядеть приблизительно так:
<html>
<head>
<meta charset="utf-8">
<title>Пятнашки</title>
<script src="puzzle15.js"></script>
</head>
<body>
<canvas id="puzzle15">Пора уже в этой жизни что-то менять</canvas>
<script>init();</script>
</body>
</html>
Написанием второго файла мы и будем заняты. Итак изначально мы напишем функцию init, которая изменит размер нашего холста и закрасит его однородым цветом, т.е. содержимое файла puzzle15.js должно быть таким:
function init() {
var canvas = document.getElementById("puzzle15");
canvas.width = 320; // задаём размеры холста
canvas.height = 320;
var context = canvas.getContext("2d");
context.fillStyle = "#222"; // цвет "заливки"
context.fillRect(0, 0, canvas.width, canvas.height); // закрашиваем холст
}
Если открыть браузером файл index.htm, то можно увидеть тёмно-серый прямоугольник. Для пятнашек я заготовил один класс в который вынесена вся игровая логика, этот класс собственно надо поместить в файл:
function game15() {
var cellView = null;
var numView = null;
var arr = [[1,2,3,4], [5,6,7,8], [9,10,11,12], [13,14,15,0]];
var clicks = 0;
function getNull() { // функция возвращает координату пустой клетки
for (var i = 0; i < 4; i++) {
for (var j = 0; j < 4; j++) {
if (arr[j][i] === 0) {
return{"x":i,"y":j};
}
}
}
};
// функция возвращает произвольное логическое значение
function getRandomBool() {
if (Math.floor(Math.random() * 2) === 0) {
return true;
}
}
// метод возвращает число касаний
this.getClicks = function() {
return clicks;
};
// метод перемещает "пятнашку" в пустую клутку
this.move = function(x, y) {
var nullX = getNull().x;
var nullY = getNull().y;
if (((x - 1 == nullX || x + 1 == nullX) && y == nullY) || ((y - 1 == nullY || y + 1 == nullY) && x == nullX)) {
arr[nullY][nullX] = arr[y][x];
arr[y][x] = 0;
clicks++;
}
};
// проверка условия победы
this.victory = function() {
var e = [[1,2,3,4], [5,6,7,8], [9,10,11,12], [13,14,15,0]];
var res = true;
for (var i = 0; i < 4; i++) {
for (var j = 0; j < 4; j++) {
if (e[i][j] != arr[i][j]) {
res = false;
}
}
}
return res;
};
// метод "перемешивает" пятнашки
this.mix = function(stepCount) {
var x,y;
for (var i = 0; i < stepCount; i++) {
var nullX = getNull().x;
var nullY = getNull().y;
var hMove = getRandomBool();
var upLeft = getRandomBool();
if (!hMove && !upLeft) { y = nullY; x = nullX - 1;}
if (hMove && !upLeft) { x = nullX; y = nullY + 1;}
if (!hMove && upLeft) { y = nullY; x = nullX + 1;}
if (hMove && upLeft) { x = nullX; y = nullY - 1;}
if (0 <= x && x <= 3 && 0 <= y && y <= 3) {
this.move(x, y);
}
}
clicks = 0;
};
// внешний вид пятнашки
this.setCellView = function(func) {
cellView = func;
};
// параметры шрифта цифр
this.setNumView = function(func) {
numView = func;
};
// Метод рисующий наши пятнашки на холсте
this.draw = function(context, size) {
for (var i = 0; i < 4; i++) {
for (var j = 0; j < 4; j++) {
if (arr[i][j] > 0) {
if (cellView !== null) {
cellView(j * size, i * size);
}
if (numView !== null) {
numView();
context.fillText(arr[i][j], j * size + size / 2, i * size + size / 2);
}
}
}
}
};
}
Теперь нашу игру можно смело перевоплотить из статичного прямоугольника, в практически рабочие пятнашки
function init() {
var canvas = document.getElementById("puzzle15");
canvas.width = 320;
canvas.height = 320;
var cellSize = canvas.width / 4;
var context = canvas.getContext("2d");
var field = new game15(); // создаём объект пятнашек
field.mix(350); // тщательно перемешиваем содердимое коробки
field.setCellView(function(x, y) { // задаём внешний вид пятнашек
context.fillStyle = "#FFB93B";
context.fillRect(x+1, y+1, cellSize-2, cellSize-2);
});
field.setNumView(function() { // параметры шрифта для цифр
context.font = "bold "+(cellSize/2)+"px Sans";
context.textAlign = "center";
context.textBaseline = "middle";
context.fillStyle = "#222";
});
context.fillStyle = "#222";
context.fillRect(0, 0, canvas.width, canvas.height);
field.draw(context, cellSize);
}
Ну вот осталось добавить лишь обработку событий мыши и касаний, и у нас получиться вполне рабочая версия пятнашек, для этого в функцию init после последней строки field.draw(context, cellSize) добавим немного кода:
function event(x, y) { // функция производит необходимые действие при клике(касанию)
field.move(x, y);
context.fillStyle = "#222";
context.fillRect(0, 0, canvas.width, canvas.height);
field.draw(context, cellSize);
if (field.victory()) { // если головоломка сложена, то пятнашки заново перемешиваются
alert("Собрано за "+field.getClicks()+" касание!"); // вывод сообщения о выигрыше!!
field.mix(300);
context.fillStyle = "#222";
context.fillRect(0, 0, canvas.width, canvas.height);
field.draw(context, cellSize);
}
}
canvas.onclick = function(e) { // обрабатываем клики мышью
var x = (e.pageX - canvas.offsetLeft) / cellSize | 0;
var y = (e.pageY - canvas.offsetTop) / cellSize | 0;
event(x, y); // выхов функции действия
};
canvas.ontouchend = function(e) { // обрабатываем касания пальцем
var x = (e.touches[0].pageX - canvas.offsetLeft) / cellSize | 0;
var y = (e.touches[0].pageY - canvas.offsetTop) / cellSize | 0;
event(x, y);
};
Кто хочет сразу поиграть для того ссылка.
Ничего сложного в коде нет, и всё пишется очень быстро. Спасибо пользователю hobbeat за идею и фотографию пятнашек на айПоде.