您好,欢迎访问一九零五行业门户网

HTML5技术之图像处理:一个滑动的拼图游戏

html5有许多功能特性可以把多媒体整合到网页中。使用canvas元素可以在这个空白的画板上填充线条,载入图片文件,甚至动画效果。
在这篇文章中,我将做一个滑动拼图的游戏用来展示html5 canvas的图片处理能力。
在网页中使用canvas标签用来创建画板。
复制代码
canvas的宽和高使用像素为单位。如果这两个属于没有被指定,他们的默认的宽度为:300px,高度为:150px。在图板画图需要使用canvas的上下文环境,通过脚本调用getcontext()方法获取上下文环境。w3c定义它为二维,更确切的说是2d。所以初始化上下文环境如果如下方法:
document.getelementbyid(vanvas).getcontext(2d);
复制代码
下一步要做的是在画板上显示图片,api只提供drawimage()一种方法。但是有三种调用方式。最常用的是传入三个参数:image对象,以及图片相对于画板的x,y坐标。
drawimage(image, x, y);
复制代码
还可以加入两个参数用于设置图片的宽和高
drawimage(image, x, y, width, height);
复制代码
最复杂的drawimage函数有9个参数,按顺序分别为:图片对象,图片x坐标,图片y坐标,图片宽,图片高,目标x坐标,目标y坐标,目标宽和目标高。后四个参数主要是为了截取原图部分用来显示,比如局部放大、剪切等。以上就是图像处理的方法,让我们做一个练习。
easy
hard
复制代码
上面的div包括了另一个html5标签:range input,这个标签可以让用户拖放滑块选择一个数值。回头我们再说在拼图中如何与range input交互。到目前为止ie和firefox并不支持这个标签。
现在就像我上面说过,想要在canvas上绘图,我们需要context。
var context = document.getelementbyid(puzzle).getcontext(2d);
复制代码
对了我们还需要一个图片,使用例子里自带的,或者找一个和canvas相同大小的图片都行。
var img = new image();
img.src = 'http://www.brucealderman.info/images/dimetrodon.jpg';
img.addeventlistener('load', drawtiles, false);
复制代码
加入这个事件是确保图片完成加载后,再把图片放入canvas中。下面我们通过range input设置拼图的数量,数据范围从3到5(几行几列)。
var boardsize = document.getelementbyid('puzzle').width;
var tilecount = document.getelementbyid('scale').value;
复制代码
有了上面两个数值就可以计算一个拼图的大小了
var tilesize = boardsize / tilecount;
复制代码
ok我们开始创建画板
var boardparts = new object;
setboard();
复制代码
setboard()的作用是初始化看板,要模拟显示这个画板,我们使用一个二维数组。不过用javascript创建这样数组的过程不是很优雅,我们先定义一个平面数组,每个数组再定义一个数组。这个拼图游戏,每一个元素都是一个对象,它带有x和y坐标记录所在的网格位置。因此每个对象有两个坐标,第一个坐标是数组坐标,表示它在画板的位置,另外的坐标是对象的x,y属性,它记录着拼图图片的位置。当这两个坐标相同了就说明位置正确。
为了达到目的,我们在初始化的时候把它们的位置互换。这样拼图就不在正确的位置了。
function setboard() {
    boardparts = new array(tilecount);
    for (var i = 0; i      boardparts[i] = new array(tilecount);
     for (var j = 0; j       boardparts[i][j] = new object;
      boardparts[i][j].x = (tilecount - 1) - i;
      boardparts[i][j].y = (tilecount - 1) - j;
     }
}
    emptyloc.x = boardparts[tilecount - 1][tilecount - 1].x;
    emptyloc.y = boardparts[tilecount - 1][tilecount - 1].y;
    solved = false;
}
复制代码
最后三个变量我们还没有定义
我们必须追踪空白拼图的位置还要记录用户点击的位置
var clickloc = new object;
clickloc.x = 0;
clickloc.y = 0;
var
emptyloc = new object;
emptyloc.x = 0;
emptyloc.y = 0;
复制代码
最后这个变量是指拼图是否完成
var solved = false;
复制代码
所有的拼图都找到正确的位置后,设置它为true。
现在我们需要一些和解决拼图相关的方法
首先为rang input定义触发事件,当它改变了,我们要重新计算拼图的数量和大小
document.getelementbyid('scale').onchange = function() {
tilecount = this.value;
    tilesize = boardsize /
tilecount;
    setboard();
drawtiles();
};
复制代码
还要追踪鼠标经过的拼图以及哪个拼图被点击
document.getelementbyid('puzzle').onmousemove = function(e)
{
    clickloc.x = math.floor((e.pagex - this.offsetleft) /
tilesize);
    clickloc.y = math.floor((e.pagey -
this.offsettop) / tilesize);
};
document.getelementbyid('puzzle').onclick
= function() {
    if (distance(clickloc.x, clickloc.y,
emptyloc.x, emptyloc.y) == 1) {
slidetile(emptyloc, clickloc);
drawtiles();
    }
    if (solved)
{
        alert(you solved
it!);
    }
};
复制代码
有一些浏览器会在重画画板之前弹出对话框,为了防止它的发生,一定要用延迟。
if (solved) {
    settimeout(function() {alert(you solved
it!);}, 500);
}
复制代码
当一个拼图被点击时,我们要知道它的四周是否可以移动。判断的方法是当前位置到空白位置的总距离为1时就可以移动。
简单点说就是x相同要判断y的距离是否为1,y相同要判断x的距离是否为1。
function distance(x1, y1, x2, y2) {
    return math.abs(x1 -
x2) + math.abs(y1 - y2);
}
复制代码
移动拼图的做法是,我们复制被点击拼图的坐标到空位置。然后把点击位置设置成空白坐标。
function slidetile(toloc, fromloc) {
    if (!solved)
{
        boardparts[toloc.x][toloc.y].x =
boardparts[fromloc.x][fromloc.y].x;
boardparts[toloc.x][toloc.y].y =
boardparts[fromloc.x][fromloc.y].y;
boardparts[fromloc.x][fromloc.y].x = tilecount -
1;
boardparts[fromloc.x][fromloc.y].y = tilecount -
1;
        toloc.x =
fromloc.x;
        toloc.y =
fromloc.y;
checksolved();
    }
}
复制代码
一旦拼图移动了,我们还要检查一下拼图是否全部在正确的位置。
function checksolved() {
    var flag =
true;
    for (var i = 0; i {
        for (var j = 0; j tilecount; ++j)
{
            if
(boardparts[i][j].x != i || boardparts[i][j].y != j)
{
flag =
false;
}
        }
}
    solved = flag;
}
复制代码
如果有一个拼图不正确函数就会返回false,否则返回true。
最后,重绘被点击的拼图到新的位置。
function drawtiles() {
    context.clearrect ( 0 , 0 , boardsize , boardsize );
    for (var i = 0; i         for (var j = 0; j             var x = boardparts[i][j].x;
     var y = boardparts[i][j].y;
            if(i != emptyloc.x || j != emptyloc.y || solved == true) {
                context.drawimage(img, x * tilesize, y * tilesize, tilesize, tilesize,
                     i * tilesize, j * tilesize, tilesize, tilesize);
            }
        }
    }
}
复制代码
当画拼图时,这个函数可以防止填充画板时匹配空的位置,因为在游戏中用户可以选择不同的难度。
转自天地会
其它类似信息

推荐信息