小游戏:移动端拼图实现

2,229 阅读4分钟
原文链接: lucc.ml

以前一直想写些自己感兴趣的东西玩,一直没动笔,还记得去年也做过小游戏方面的工作,当时基本上都是在网上找现成的改改就OK了,还记得以前想找个移动端的拼图找了好久都没找到,懊悔不已,最近研究了下,写个玩玩。

demo地址体验
源码地址

PC端的尝试

  • 解决拖拽问题网上搜了下解决方案:

    思路一:鼠标在页面上移动时不断获取鼠标位置,并将鼠标的位置信息赋值给随鼠标移动的标签,对标签进行定位;这样鼠标就能进行拖动标签了。


    思路二:HTML5新属性,可拖放属性draggable,支持draggable属性的浏览器有IE10+,Firfox4+,Safari5+,Chrome,另外为了让Firfox支持可拖放属性,还必须添加一个ondragstart事件处理程序,并在dataTransfer对象中保存一些信息。
  • 解决图片切割问题
    图片切割本来想就用背景图搞个定位完事,后来想想,还是为难下自己,用过几次canvas,感觉还不错,所以这次用用canvas,具体用到了drawImage这个方法,方法后文贴出

  • 校验拼图完成
    自己想的一个办法,将正确的索引连起来组成一个字符串,render图片的时候,为每张图分配一个id,每次运动完成,拼接当前所有图片的id组成一个字符串和正确索引的字符串相比较,若相等,则拼图完成。

  • 最终选择思路二小试一把,为了方便,还引用了jquery
    记录下用到的拖拽方法:

$drag[l].ondragstart = function(ev) {
    /*拖拽开始*/
    return true;
};
$drag[l].ondrag=function(ev){
    /*console.log("move%o",ev);*/
    return true;
};
$drag[l].ondragend = function(ev) {
    /*拖拽结束*/
    return false
};
$drag[l].ondragover = function(ev) {
    /*拖拽元素在目标元素头上移动的时候*/
    return true;
};
$drag[l].ondragenter = function(ev) {
    /*拖拽元素进入目标元素头上的时候*/
    return true;
};
$drag[l].ondrop = function(ev) {
    /*拖拽元素进入目标元素头上,同时鼠标松开的时候*/
    return false;
};

移动端的尝试

有了pc端的尝试,一些逻辑方面的已经理清,正式着手移动端

  • 拖拽问题
    主要用到了移动端的touch事件,toustart,touchmove,touchend这三个事件

  • 解决图片切割问题
    和pc端用到的方法一样

  • 校验拼图完成
    后来想想pc端用的方法太繁琐了,后来改进了下,大致思路一样,稍后代码贴出

图片切割问题

根据参数numbs确认要切割的数量,求出每个小图在原图片上的坐标,用canvas切割出来放到数组里

for(var i=0;i
打乱图片顺序,遍历存放图片的数组将key放到一个新的数组里,同时创建一个新的对象存放数组的key,value,对key数组打乱顺序,最后取出res[keys[i]]
var res={},keys=[];
for(var i=0;i
取打乱的数组部分
var numbs=this.numbs;
var keys=this.getlist(arr);
for(var i=0;i
图片跟随手指移动 先算出手指据当前图片的距离tempX、tempY备用
_start:function(evt){
    this.startTime = new Date().getTime();
    this._startX=evt.touches[0].pageX;
    this._startY=evt.touches[0].pageY;
    this.tochEvent=evt.target.parentElement;
    this.tochEvent.classList.remove("trans");
    this.resetIndex(this.tochEvent);
    this.tempX=this._startX-this.tochEvent.offsetLeft;//手指据当前图片的左距离
    this.tempY=this._startY-this.tochEvent.offsetTop;//手指据当前图片的顶距离
    console.log("evt%o",evt);
    console.dir(this.tochEvent);
}
```  
###### touchmove 手指移动触发
```javascripe
_move:function(evt){
    var _moveX=evt.touches[0].pageX;
    var _moveY=evt.touches[0].pageY;    
    var x=_moveX-this.tempX;//手指距屏幕左边距的距离减去手指距当前图片的距离
    var y=_moveY-this.tempY;
    ...
    this.tochEvent.style.left=x+"px";
    this.tochEvent.style.top=y+"px";
    evt.preventDefault();
}
勾股定理判断与当前元素最近的目标

getDistance:function(obj1,obj2){
    var a=(obj1.offsetLeft+obj1.offsetWidth/2)-(obj2.offsetLeft+obj2.offsetWidth/2);
    var b=(obj1.offsetTop+obj1.offsetHeight/2)-(obj2.offsetTop+obj2.offsetHeight/2);
    return Math.ceil(Math.sqrt(a * a + b * b));
},

这里用了个蠢办法 遍历所有dom 算与当前dom的中心点的距离,找出最近距离,并输出,以前看到过别人用了更好的方法来碰撞检测 好像是用圆,忘了。。数学没学好。。

getshortdistance:function(el){
    var list=this.lis,res=[];
    for(var i=0;i
松开手指替换两张图片的src及编号
oldImg.src=this.list[newEl.idx];
newImg.src=this.list[oldEl.idx];
oldEl.idx=newEl.idx;
newEl.idx=temp;
//位置复原
oldEl.classList.add("trans");
oldEl.style.left=oldEl.positionList.x+"px";
oldEl.style.top=oldEl.positionList.y+"px";
校验是否拼图完成,这里的检测主要是对比打乱的索引idx和正确的索引是否相等,若全部相等 则拼图完成
var list=[].slice.call(this.lis);//将dom数组转化为数组
var flag=list.every(function(item,index,array){
    return item.idx==item.index;
});
if(flag){
    this.pass && this.pass(this.startIndex);
}

总结

写完后发现没啥应用场景,就当练练手,写着玩玩了。。手机体验扫描下述二维码

image