Ранее я опубликовал урок о том, как создать игру пятнашки на Flash. Чуть позже мы портировали игру на Андроид сделав сборку с помощью Adobe Air и переписав управление под мультитач.
Теперь попробуем перевести игру рельсы HTML5. Использовать для будем исключительно элемент canvas (без CSS).
Самое главное отличие от flash-версии конечно будет способ отображения графической составляющей. Примитивная графика в нашей игре может быть программно сгенерирована прямо налету. Поэтому все элементы будем рисовать прямо на канвасе.
И так, приступим. Элементу <canvas> я задал id="map". Логика игры полностью повторяет логику flash-версии и просто переписана на Javascript.
Вот, что в итоге у нас получилось:
Теперь попробуем перевести игру рельсы HTML5. Использовать для будем исключительно элемент canvas (без CSS).
Самое главное отличие от flash-версии конечно будет способ отображения графической составляющей. Примитивная графика в нашей игре может быть программно сгенерирована прямо налету. Поэтому все элементы будем рисовать прямо на канвасе.
И так, приступим. Элементу <canvas> я задал id="map". Логика игры полностью повторяет логику flash-версии и просто переписана на Javascript.
window.onload = init; var map; var ctxMap; var gameWidth=288; var gameHeight=400; var matrix = [[],[],[],[]] ; var checkMatrix = [[1, 2, 3, 4 ], [5, 6, 7, 8 ], [9, 10, 11, 12], [13, 14, 15, 0 ] ] ; var randomMas=[]; var countMc; var moveCount=0; var flagVictory=false; function init(){ map = document.getElementById("map"); map.width=gameWidth; map.height=gameHeight; ctxMap = map.getContext("2d"); game(); map.addEventListener("click", clickFunc, false); } var Tile = function(){ this.i=0; this.j=0; this.x=0; this.y=0; this.number=0; this.addTile = function(){ ctxMap.fillStyle="#FFFFE8"; ctxMap.fillRoundedRect(this.x, this.y, 64, 64, 10); } this.setText=function(text){ with (ctxMap){ font = '20pt impact'; textBaseline = 'top'; textAlign = 'center'; fillStyle = '#000'; fillText(text, this.x+31, this.y+20); } } this.clearTile = function(){ ctxMap.fillStyle="#CCFFFF"; ctxMap.fillRoundedRect(this.x, this.y, 64, 64, 10); } } function clickFunc(e){ for (var j = 0; j < 4; j++ ) { for (var i = 0; i < 4; i++ ) { if (matrix[i][j].x+64 > e.offsetX && matrix[i][j].x < e.offsetX && matrix[i][j].y+64 > e.offsetY && matrix[i][j].y < e.offsetY ) move(matrix[i][j]); }} if (44.7+64 > e.offsetX && 44.7 < e.offsetX && 326.5+64 > e.offsetY && 326.5 < e.offsetY ) newRandGame(); } // обработка клика на плику, перемещение плит function move(e) { var currNumber = e.number; // сохраняем номер текущей плитки if (currNumber != 0 && !flagVictory) { // если это не пустое поле и не победное положение, то продолжаем var i = e.i; // сохраним координаты плитки в матрице var j = e.j; var flag = false; // флаг для определения завершения хода for (var k = 0; k < 4; k++ ) { // нам нужно проверить наличие пустой плитки с четырёх сторон switch(k) { case 0 :{ if (i+1 < 4 && matrix[i + 1][j].number == 0) { // если плитка не крайняя и снизу есть пустое поле, то matrix[i + 1][j].addTile(); // пустое поле превращаем в плитку matrix[i + 1][j].setText(e.number); // задаем новой плитке строку с числом matrix[i + 1][j].number = currNumber; // теперь новая плитка превратилась в ту, на которую мы нажали flag = true; // говорим что ход заврешен }; break; } case 1 :{ if (j+1 < 4 && matrix[i][j+1].number == 0) { matrix[i][j + 1].addTile(); matrix[i][j + 1].setText(e.number); matrix[i][j + 1].number = currNumber; flag = true; }; break; } case 2 :{ if (i-1 > -1 && matrix[i - 1][j].number == 0) { matrix[i - 1][j].addTile(); matrix[i - 1][j].setText(e.number); matrix[i - 1][j].number = currNumber; flag = true; }; break; } case 3 :{ if (j-1 > -1 && matrix[i][j-1].number == 0) { matrix[i][j - 1].addTile(); matrix[i][j - 1].setText(e.number); matrix[i][j - 1].number = currNumber; flag = true; }; break; } } if (flag) { // если ход завершен matrix[i][j].number = 0; // текущую плитку делаем пустым полем e.clearTile(); moveCount++; // счетчик ходов setCountMc(moveCount); // увеличиваем счетчик // if(check()) flagVictory=true; // проверка на победу break; } } } } function game(){ ctxMap.fillStyle="#CECECE"; ctxMap.fillRect(0,0,gameWidth,gameHeight); setRestartBtn(); setCountMc(0); setTiles(); } function setRestartBtn() { with (ctxMap){ fillStyle="#333333"; fillRoundedRect(44.7, 326.5, 50, 50, 10); font = '10pt impact'; textBaseline = 'top'; textAlign = 'left'; fillStyle = '#ffffff'; fillText("Restart", 44.7+5, 326.5+17); } } function setCountMc(string) { with (ctxMap){ fillStyle="#333333"; fillRoundedRect(192.55, 326.5, 50, 50, 10); font = '10pt impact'; textBaseline = 'top'; textAlign = 'left'; fillStyle = '#ffffff'; fillText("MOVES", 192.55+7, 326.5+5); font = '18pt impact'; textAlign = 'center'; fillText(string, 192.55+25, 326.5+22); } } function setTiles(){ for (var j=0; j<4; j++){ for (var i=0; i<4; i++){ matrix[i][j]=new Tile(); matrix[i][j].i=i; matrix[i][j].j=j; matrix[i][j].x=4+i*64+8*i; matrix[i][j].y=4+j*64+8*j; } } newRandGame(); } // функция создания новой игры function newRandGame() { flagVictory = false; // сброс флага победы moveCount=0; // сброс счетчика ходов // countMc.Count_field.text = String(moveCount); var tempcount = 0; // временная переменная для присвоения занчений в массиве random(); // генерируем рандомную последовательность от 1 до 15 в массив for (var j = 0; j < 4; j++ ) { // в двойном цикле пишем рандомную последовательность в нашу матрицу for (var i = 0; i < 4; i++ ) { matrix[i][j].addTile(); matrix[i][j].setText(randomMas[tempcount]); //= String(randomMas[tempcount]); matrix[i][j].number = randomMas[tempcount]; tempcount++; } } matrix[3][3].clearTile(); // плитку в правом нижнем углу делаем пустым полем matrix[3][3].number = 0; } // создание масива с рандомной последовательностью от 1 до 15 function random() { var flag = true; var temp = 0; var count = 0; for (var k = 0; k < 16; k++ ) randomMas[k]=0 // обнуляем массив for (var j = 0; j <15; j++ ) { // в цикле создаем и записываем в массив 15 чисел while (flag) { // этот цикл работает до тех пор, пока не сгенерируется число, которого еще нет в массиве if (count == 15) break; temp = Math.round(15 * Math.random() + 1); flag = false; for (var i = 0; i < 16; i++ ) { // цикл проверяет сгенерированное число, на его наличие в массиве if (randomMas[i] == temp || temp==16) { flag = true; break; } } } // console.log(temp); randomMas[j] = temp; count++; flag = true; } } CanvasRenderingContext2D.prototype.fillRoundedRect = fillRoundedRect; /* x: Координата верхнего левого угла по горизонтали y: Координата верхнего левого угла по вертикали w: Ширина прямоугольника h: Высота прямоугольника r: Радиус закруглений */ function fillRoundedRect(x, y, w, h, r){ this.beginPath(); this.moveTo(x+r, y); this.lineTo(x+w-r, y); this.quadraticCurveTo(x+w, y, x+w, y+r); this.lineTo(x+w, y+h-r); this.quadraticCurveTo(x+w, y+h, x+w-r, y+h); this.lineTo(x+r, y+h); this.quadraticCurveTo(x, y+h, x, y+h-r); this.lineTo(x, y+r); this.quadraticCurveTo(x, y, x+r, y); this.fill(); }
Вот, что в итоге у нас получилось:
В этом примере я не заморачивался со шрифтами и использовал Impact, но если у вас нет в системе этого шрифта, то буквы и цифры могут немного поплыть.
Комментариев нет:
Отправить комментарий