📜 ⬆️ ⬇️

Canvas: fifteen minutes for tag

CANVAS step by step:
  1. The basics
  2. Images
  3. Pong
  4. Fifteen

In my childhood I had tags, I think everyone knows this puzzle. It was very interesting to move the tags in a plastic box to get the coveted order of numbers. And quite recently, in the order of sports interest, I wrote for myself tags that could be played not only from the browser window, but also from a smartphone running Android OS or iOS.
Our game will consist of two files lying in the same daddy, the first is called index.htm, and the second is puzzle15.js
The contents of the html file will not change during the whole post, and in fact it should look something like this:
<html> <head> <meta charset="utf-8"> <title></title> <script src="puzzle15.js"></script> </head> <body> <canvas id="puzzle15">     - </canvas> <script>init();</script> </body> </html> 

We will be busy writing the second file. So initially we will write the function init, which will change the size of our canvas and paint it with a uniform color, i.e. The contents of the puzzle15.js file should be:
 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); //   } 

If you open the index.htm file with a browser, you can see a dark gray rectangle. For Fifteen, I have prepared one class in which all the game logic is rendered, this class itself should be placed in a file:
 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); } } } } }; } 

Now our game can be safely transformed from a static rectangle into practically working tags
 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); } 

Well, it remains to add only the handling of mouse and touch events, and we’ll have a completely working version of the tags. To do this, add some code to the init function after the last line of 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); }; 

Who wants to immediately play for that link .
There is nothing complicated in the code, and everything is written very quickly. Thanks to hobbeat for the idea and photo of the Fifteen Ipod.

')

Source: https://habr.com/ru/post/118356/


All Articles