HTML 5的一个滑动拼图游戏

开发 前端
canvas的宽和高使用像素为单位。如果这两个属于没有被指定,他们的默认的宽度为:300px,高度为:150px。在图板画图需要使用canvas的上下文环境,通过脚本调用getContext()方法获取上下文环境。

HTML5有许多功能特性可以把多媒体整合到网页中。使用canvas元素可以在这个空白的画板上填充线条,载入图片文件,甚至动画效果。

在这篇文章中,我将做一个滑动拼图的游戏用来展示HTML5 canvas的图片处理能力。在网页中使用canvas标签用来创建画板。

  1. <canvas width="480px" height="480px"></canvas> 

canvas的宽和高使用像素为单位。如果这两个属于没有被指定,他们的默认的宽度为:300px,高度为:150px。在图板画图需要使用canvas的上下文环境,通过脚本调用getContext()方法获取上下文环境。W3C定义它为二维,更确切的说是2d。所以初始化上下文环境如果如下方法:

  1. document.getElementById("vanvas").getContext("2d"); 

下一步要做的是在画板上显示图片,API只提供drawImage()一种方法。但是有三种调用方式。最常用的是传入三个参数:image对象,以及图片相对于画板的x,y坐标。

  1. drawImage(image, x, y); 

还可以加入两个参数用于设置图片的宽和高

  1. drawImage(image, x, y, width, height); 

最复杂的drawImage函数有9个参数,按顺序分别为:图片对象,图片x坐标,图片y坐标,图片宽,图片高,目标x坐标,目标y坐标,目标宽和目标高。后四个参数主要是为了截取原图部分用来显示,比如局部放大、剪切等。以上就是图像处理的方法,让我们做一个练习。

  1. <div id="slider"> 
  2.   <form>      
  3.     <label>Easy</label> 
  4.     <input type="range" id="scale" value="4" min="3" max="5" step="1"> 
  5.     <label>Hard</label> 
  6.   </form> 
  7. <br> 
  8. </div> 
  9. <div id="main" class="main"> 
  10. <canvas id="puzzle" width="480px" height="480px"></canvas> 
  11. </div> 

上面的DIV包括了另一个HTML5标签:range input,这个标签可以让用户拖放滑块选择一个数值。回头我们再说在拼图中如何与range input交互。到目前为止ie和firefox并不支持这个标签。

现在就像我上面说过,想要在canvas上绘图,我们需要context。

  1. var context = document.getElementById("puzzle").getContext("2d"); 

对了我们还需要一个图片,使用例子里自带的,或者找一个和canvas相同大小的图片都行。

  1. var img = new Image();  
  2. img.src = 'http://www.brucealderman.info/Images/dimetrodon.jpg';  
  3. img.addEventListener('load', drawTiles, false); 

加入这个事件是确保图片完成加载后,再把图片放入canvas中。下面我们通过range input设置拼图的数量,数据范围从3到5(几行几列)。

  1. var boardSize = document.getElementById('puzzle').width;  
  2. var tileCount = document.getElementById('scale').value; 

有了上面两个数值就可以计算一个拼图的大小了

  1. var tileSize = boardSize / tileCount; 

OK我们开始创建画板

  1. var boardParts = new Object;  
  2. setBoard(); 

setBoard()的作用是初始化看板,要模拟显示这个画板,我们使用一个二维数组。不过用JavaScript创建这样数组的过程不是很优雅,我们先定义一个平面数组,每个数组再定义一个数组。这个拼图游戏,每一个元素都是一个对象,它带有x和y坐标记录所在的网格位置。因此每个对象有两个坐标,***个坐标是数组坐标,表示它在画板的位置,另外的坐标是对象的x,y属性,它记录着拼图图片的位置。当这两个坐标相同了就说明位置正确。

为了达到目的,我们在初始化的时候把它们的位置互换。这样拼图就不在正确的位置了。

  1. function setBoard() {  
  2.     boardParts = new Array(tileCount);  
  3.     for (var i = 0; i < tileCount; ++i) {  
  4.      boardParts[i] = new Array(tileCount);  
  5.      for (var j = 0; j < tileCount; ++j) {  
  6.       boardParts[i][j] = new Object;  
  7.       boardParts[i][j].x = (tileCount - 1) - i;  
  8.       boardParts[i][j].y = (tileCount - 1) - j;  
  9.      }  
  10. }  
  11.     emptyLoc.x = boardParts[tileCount - 1][tileCount - 1].x;  
  12.     emptyLoc.y = boardParts[tileCount - 1][tileCount - 1].y;  
  13.     solved = false;  

***三个变量我们还没有定义

我们必须追踪空白拼图的位置还要记录用户点击的位置

  1. var clickLoc = new Object;  
  2. clickLoc.x = 0;  
  3. clickLoc.y = 0;  
  4. var   
  5. emptyLoc = new Object;  
  6. emptyLoc.x = 0;  
  7. emptyLoc.y = 0

***这个变量是指拼图是否完成

  1. var solved = false

所有的拼图都找到正确的位置后,设置它为true。

现在我们需要一些和解决拼图相关的方法

首先为rang input定义触发事件,当它改变了,我们要重新计算拼图的数量和大小

  1. document.getElementById('scale').onchange = function() {  
  2.       
  3. tileCount = this.value;  
  4.     tileSize = boardSize /   
  5. tileCount;  
  6.     setBoard();  
  7.       
  8. drawTiles();  
  9. }; 

还要追踪鼠标经过的拼图以及哪个拼图被点击

  1. document.getElementById('puzzle').onmousemove = function(e)   
  2. {  
  3.     clickLoc.x = Math.floor((e.pageX - this.offsetLeft) /   
  4. tileSize);  
  5.     clickLoc.y = Math.floor((e.pageY -   
  6. this.offsetTop) / tileSize);  
  7. };  
  8. document.getElementById('puzzle').onclick   
  9. function() {  
  10.     if (distance(clickLoc.x, clickLoc.y,   
  11. emptyLoc.x, emptyLoc.y) == 1) {  
  12.           
  13. slideTile(emptyLoc, clickLoc);  
  14.           
  15. drawTiles();  
  16.     }  
  17.     if (solved)   
  18. {  
  19.         alert("You solved   
  20. it!");  
  21.     }  
  22. }; 

有一些浏览器会在重画画板之前弹出对话框,为了防止它的发生,一定要用延迟。

  1. if (solved) {  
  2.     setTimeout(function() {alert("You solved   
  3. it!");}, 500);  

当一个拼图被点击时,我们要知道它的四周是否可以移动。判断的方法是当前位置到空白位置的总距离为1时就可以移动。

简单点说就是x相同要判断y的距离是否为1,y相同要判断x的距离是否为1。

  1. function distance(x1, y1, x2, y2) {  
  2.     return Math.abs(x1 -   
  3. x2) + Math.abs(y1 - y2);  

移动拼图的做法是,我们复制被点击拼图的坐标到空位置。然后把点击位置设置成空白坐标。

  1. function slideTile(toLoc, fromLoc) {  
  2.     if (!solved)   
  3. {  
  4.         boardParts[toLoc.x][toLoc.y].x =   
  5. boardParts[fromLoc.x][fromLoc.y].x;  
  6.           
  7. boardParts[toLoc.x][toLoc.y].y =   
  8. boardParts[fromLoc.x][fromLoc.y].y;  
  9.           
  10. boardParts[fromLoc.x][fromLoc.y].x = tileCount -   
  11. 1;  
  12.           
  13. boardParts[fromLoc.x][fromLoc.y].y = tileCount -   
  14. 1;  
  15.         toLoc.x =   
  16. fromLoc.x;  
  17.         toLoc.y =   
  18. fromLoc.y;  
  19.           
  20. checkSolved();  
  21.     }  

一旦拼图移动了,我们还要检查一下拼图是否全部在正确的位置。

  1. function checkSolved() {  
  2.     var flag =   
  3. true;  
  4.     for (var i = 0; i < tileCount; ++i)   
  5. {  
  6.         for (var j = 0; j <   
  7. tileCount; ++j)   
  8. {  
  9.             if   
  10. (boardParts[i][j].x != i || boardParts[i][j].y != j)   
  11. {  
  12.                   
  13. flag =   
  14. false;  
  15.               
  16. }  
  17.         }  
  18.       
  19. }  
  20.     solved = flag;  

如果有一个拼图不正确函数就会返回false,否则返回true。

***,重绘被点击的拼图到新的位置。

  1. function drawTiles() {  
  2.     context.clearRect ( 0 , 0 , boardSize , boardSize );  
  3.     for (var i = 0; i < tileCount; ++i) {  
  4.         for (var j = 0; j < tileCount; ++j) {  
  5.             var x = boardParts[i][j].x;  
  6.      var y = boardParts[i][j].y;  
  7.             if(i != emptyLoc.x || j != emptyLoc.y || solved == true) {  
  8.                 context.drawImage(img, x * tileSize, y * tileSize, tileSize, tileSize,  
  9.                      i * tileSize, j * tileSize, tileSize, tileSize);  
  10.             }  
  11.         }  
  12.     }  

当画拼图时,这个函数可以防止填充画板时匹配空的位置,因为在游戏中用户可以选择不同的难度。

原文链接:http://www.html5cn.org/article-2655-1.html

【编辑推荐】

  1. HTML 5实现淘宝语音搜索功能
  2. 别怕!我们还有HTML 5和CSS3
  3. 难以置信的HTML 5和JS实验
  4. HTML 5做出让你意想不到的几件事
  5. 用HTML***udio API开发游戏音乐
责任编辑:张伟 来源: HTML5中国
相关推荐

2012-09-24 11:11:32

HTML5游戏开发JavaScript

2022-08-04 06:57:54

CSS拼图游戏

2021-11-01 10:26:07

CanvasAPI画布技术HTML5

2011-11-18 16:09:37

jQuery

2022-02-17 20:18:27

JS鸿蒙操作系统

2012-03-29 09:18:47

HTML5WEB

2021-08-15 22:52:30

前端H5拼图

2012-03-09 09:37:01

HTML 5

2012-09-24 09:46:20

JavaScriptJSHTML5

2018-01-19 14:25:18

游戏

2010-02-05 09:28:13

HTML5Flash

2012-05-09 09:41:58

HTML5

2012-05-28 15:31:57

App-UI

2011-12-21 09:38:31

HTML 5

2012-05-10 09:45:14

HTML5

2015-12-03 15:22:01

HTML5游戏建议

2014-12-30 17:13:51

HTML5

2013-12-19 09:58:36

移动应用产品市场

2012-04-25 14:06:45

HTML5

2012-09-11 13:34:27

HTML5JS
点赞
收藏

51CTO技术栈公众号