本文实例为大家分享了用js编写实现拼图游戏的具体代码,供大家参考,具体内容如下
目标
使用原生js编写一个拼图游戏,我这里写了两种拼图的方法。一种是拖拽拼图,一种是经典的九宫格拼图,可以自定义参数设置游戏难度
先看看截图效果
拖拽模式(拖拽图片切换图片)
点击模式(点击图片与空白区域切换位置)
不多说,直接上代码
css
#canvasbox{ margin: 0 auto; position: fixed; border: 2px solid #f00; overflow: hidden; } .item{ display: inline-block; border: 1px solid #f00; position: absolute; top: 0; left: 0; transition: 0.1s; }
html
<div style="margin: 0 auto;text-algin:center;"> <button onclick="setgame('block', 'none')">拖拽模式</button> <button onclick="setgame('none', 'block')" >点击模式</button> </div> <div id="canvasbox"></div> <div id="canvasbox2"></div>
javascript
/* * @title jigsawgame 拼图游戏 * @params obj object 游戏参数 * { * @param id string 容器id * @param imgurl string 图片路径 * @param level number 游戏难度 简单:1 || 普通:2 || 困难:3 * @param gametype number 游戏类型 拖动版本:1 || 点击版本:2 * } * @author beideng */ function jigsawgame(obj){ // 初始化容器 this.id = document.getelementbyid(obj.id); // 初始化图片 this.img = new image(); this.img.src = obj.imgurl; // 容器最大宽度 this.windowwidth = document.body.clientwidth; this.maxwidth = this.windowwidth > 750 ? 750 : (this.windowwidth * 0.9); // 设置容器宽高 this.id.style.width = this.maxwidth + "px"; this.id.style.height = this.maxwidth + "px"; this.id.style.left = (this.windowwidth - this.maxwidth)/2 + "px"; this.id.style.top = 50 + "px"; // 获取容器范围 this.boxoffsety = parsefloat(this.id.style.top); this.boxoffsetx = parsefloat( this.id.style.left); // 关卡(简单:1 || 普通:2 || 困难:3) if(obj.level == 1 || obj.level == 2 || obj.level == 3 ){ this.level = obj.level; }else{ this.level = 1; } // 难度 var diffarr = [3, 4, 5]; this.diff= diffarr[this.level-1]; // canvas宽高 this.cw = this.maxwidth/ this.diff; this.ch = this.maxwidth/ this.diff; // 记录的小方块个数 this.number = 0; // 正确的数组 this.numberarr = []; // 存储小方块的中心点坐标 this.centerxy = []; /* * 获取游戏类型 */ this.gametype = obj.gametype || 1; // 记录最后一个元素的标记 this.lastelement = { sign: 0, left: 0, top: 0, id: obj.id + 1 }; // 初始化 this.init(); } /* * 操作方法 * */ jigsawgame.prototype = { /* * @method 初始化 */ init: function(){ var that = this; this.img.onload = function(){ // 格子宽高 var levelw = that.img.width/that.diff; var levelh = that.img.height/that.diff; for(var i = 0 ; i < that.diff; i++){ for(var j = 0 ; j < that.diff; j++){ // 初始化小方块 that.initcube(i, j, levelw, levelh); } } // 打乱小方块 that.upsetelement(); // 游戏类型判断 if(that.gametype == 1){ // 监听拖动 that.id.addeventlistener("mousedown",function(event){ that.mousedown(event); }, false); }else{ // 获取空白小方块坐标 that.getlastelement(); // 监听点击 that.id.addeventlistener("click",function(event){ that.mouseclick(event); }, false); } } }, /* * @method 初始化小方块 * @param i number 循环值 * @param j number 循环值 * @param j levelw 小方块宽 * @param j levelh 小方块高 */ initcube: function(i, j, levelw, levelh){ // 创建一个小方块 var item = document.createelement("div"), cw = this.cw, ch = this.ch; item.classname = "item"; item.setattribute("data-index", this.number); item.style.width = cw + "px"; item.style.height = ch + "px"; item.style.left = i * cw + "px"; item.style.top = j * ch + "px"; item.innerhtml = "<canvas class='' width='"+ cw +"' height='"+ ch +"'></canvas>"; this.id.appendchild(item); var canvas = item.queryselector("canvas"); var ctx = canvas.getcontext("2d"); /* * 当游戏为点击类型时 * 去掉最后一个小方块里的图片 * 且记录当前元素的坐标以及编号 */ if(this.gametype != 1 && j == this.diff-1 && i == this.diff-1){ this.lastelement.sign = this.number; item.id = this.lastelement.id; }else{ ctx.drawimage(this.img, i * levelw, j * levelh , levelw, levelh, 0 , 0, cw, ch) } // 每添加一个就压入一次到数组 this.numberarr.push({ x: i*cw +"px" , y: j*ch +"px" }); this.number++; // 压入初始中心点 this.centerxy.push({ x: i*cw + cw / 2, y: j*ch + ch / 2 }); }, /* * @method 悬停拖住小方块 * @param event object 鼠标对象 */ mousedown: function(event){ console.log(event) var event = event || window.event; var that = this; var target = event.target || event.srcelement; // 保证拖动的是想要的元素 if( target.parentelement.classname.tolowercase() == "item"){ var element = target.parentelement; // 存储当前元素的top,left var thistop = parsefloat( element.style.top ); var thisleft = parsefloat( element.style.left ); // 获取当前点击的位置 var pagex = event.pagex; var pagey = event.pagey; // 拖动 document.onmousemove = function(e){ console.log(e) that.mousemove(e, element, thistop, thisleft, pagey, pagex); return false; } // 松开 document.onmouseup = function(e){ that.mouseup(e, element, thistop, thisleft) // 释放拖拽 document.onmousemove = null; document.onmouseup = null; return false; } } return false; }, /* * @method 拖动小方块 * @param e object 鼠标对象 */ mousemove: function(e, element, thistop, thisleft, pagey, pagex){ var pagex2 = e.pagex; var pagey2 = e.pagey; element.style.top = thistop + (pagey2 - pagey) + "px"; element.style.left = thisleft + (pagex2 - pagex) + "px"; element.style.zindex = 1000; }, /* * @method 松开小方块 * @param e object 鼠标对象 */ mouseup: function(e, element, thistop, thisleft){ var that = this, cw = this.cw, ch = this.ch; // 检测当前拖动替换目标 var movecenterx = parsefloat(element.style.left) + cw / 2; var movecentery = parsefloat(element.style.top) + ch / 2; var changeelementindex = this.checkchangeelement(movecenterx, movecentery); var changeelement = this.id.getelementsbyclassname("item")[changeelementindex]; // 限制拖拽范围 // 当松开的坐标xy在容器范围内 if( e.pagex < this.boxoffsetx || e.pagex > (this.boxoffsetx + this.maxwidth) || e.pagey < this.boxoffsety || e.pagey > (this.boxoffsety + this.maxwidth) ){ console.log("释放") element.style.top = thistop + "px"; element.style.left = thisleft + "px"; }else{ // 判断当前元素是否离开了自己的格子 if( element.getattribute("data-index") == changeelement.getattribute("data-index")){ element.style.top = thistop + "px"; element.style.left = thisleft + "px"; }else{ // 进行替换 element.style.top = changeelement.style.top ; element.style.left = changeelement.style.left ; changeelement.style.top = thistop + "px"; changeelement.style.left = thisleft + "px"; changeelement.style.zindex = 1000; // 更新小方块中心点 this.updateelement(); } } // 消除层级问题 settimeout(function(){ element.style.zindex = 0; changeelement.style.zindex = 0; if(that.comparearray()){ alert("恭喜你,拼图成功!"); } }, 150); // 判断拼图完成 console.log(this.comparearray()) console.log(this.numberarr) }, /* * @method 检测当前拖动替换目标 * @param moveleft number 鼠标移动的x值 * @param movetop number 鼠标移动的y值 * @return minindex number 返回目标对象下标 * 通过三角函数检测当前拖动对象中心点和其他所有对象中心点距离,离谁最近就和谁替换 */ checkchangeelement: function(moveleft, movetop){ // 最小距离 var mindistance = null; // 最小距离替换目标 var minindex = null; for(var i = 0 ; i < this.centerxy.length; i++){ var x = math.abs( moveleft - this.centerxy[i].x ); var y= math.abs( movetop - this.centerxy[i].y ); var val = math.ceil(math.sqrt( x * x + y * y)); // 初次判断 if(mindistance == null){ mindistance = val; minindex = i; } // 后续判断 if(mindistance > val){ mindistance = val; minindex = i; } } // 返回目标对象下标 return minindex; }, /* * @method 更新小方块中心点 */ updateelement: function(){ var allelement = this.id.getelementsbyclassname("item"), cw = this.cw, ch = this.ch; this.centerxy = []; for(var i = 0 ; i < allelement.length; i++){ this.centerxy.push({ x: parsefloat(allelement[i].style.left) + cw / 2, y: parsefloat(allelement[i].style.top) + ch / 2 }); } }, /* * @method 点击小方块 * @param event object 鼠标对象 * @ 1、点击当前非空白小方块 * @ 2、获取其坐标,并加减一个一个方块宽度,用这个加减坐标去检索空白小方块是否在目标小方块周边 * @ 3、如果在,则替换这两个小方块的坐标 */ mouseclick: function(event){ console.log(event) var event = event || window.event; var that = this; var target = event.target || event.srcelement; // 保证拖动的是想要的元素 if( target.parentelement.classname.tolowercase() == "item"){ var element = target.parentelement; // 当当前点击目标为空白小方块时,终止函数 if(element.getattribute("data-index") == this.lastelement.sign){ return ; } // 存储当前元素的top,left var thistop = parsefloat( element.style.top ); var thisleft = parsefloat( element.style.left ); // 点击检测空白方块是否在当前对象周边 if(this.mouseclickcheck(thistop, thisleft)){ console.log(222) // 获取空白元素 var lastelement = document.getelementbyid(this.lastelement.id); // 替换这两个元素的坐标 element.style.top = lastelement.style.top; element.style.left = lastelement.style.left; lastelement.style.top = thistop + "px"; lastelement.style.left = thisleft + "px"; this.lastelement.left = thisleft ; this.lastelement.top = thistop; // 消除层级问题 settimeout(function(){ if(that.comparearray()){ alert("恭喜你,拼图成功!"); } }, 150); // 判断拼图完成 console.log(this.comparearray()) console.log(this.numberarr) } } return false; }, /* * @method 点击检测空白方块是否在当前对象周边 * @param thistop number 当前点击元素的top * @param thisleft number 当前点击元素的left * @return boolean 是否在周边 */ mouseclickcheck: function(thistop, thisleft){ var cw = this.cw, ch = this.ch; if(thistop == this.lastelement.top && (thisleft - ch) == this.lastelement.left){ return true; } if(thistop == this.lastelement.top && (thisleft + ch) == this.lastelement.left){ return true; } if((thistop - cw) == this.lastelement.top && thisleft == this.lastelement.left){ return true; } if((thistop + cw) == this.lastelement.top && thisleft == this.lastelement.left){ return true; } return false; }, /* * @method 获取空白元素left,right */ getlastelement: function(){ // 获取空白元素 var lastelement = document.getelementbyid(this.lastelement.id); console.log(this.lastelement); this.lastelement.left = parsefloat(lastelement.style.left) ; this.lastelement.top = parsefloat(lastelement.style.top); }, /* * @method 打乱小方块 * 以小方块的个数为次数,每次随机抽取两个小于小方块的数,然后替换两个dom元素的定位坐标 */ upsetelement: function(){ for (var i = 0; i < this.number-1; i++) { // 获取两个不相等的随机值 var n1 = math.floor(math.random()*this.number); var n2 = math.floor(math.random()*this.number); do{ n2 = math.floor(math.random()*this.number); }while(n1 == n2) // 替换当前的两个小方块的坐标 var allelement = this.id.getelementsbyclassname("item"); var top = allelement[n1].style.top ; var left = allelement[n1].style.left ; allelement[n1].style.top = allelement[n2].style.top ; allelement[n1].style.left = allelement[n2].style.left ; allelement[n2].style.top = top ; allelement[n2].style.left = left ; } }, /* * @method 比较小方块是否拼图完成 * @return boolean * 获取切换小方块后,获取小方块的序号并与正确排序数组进行比较 */ comparearray: function(){ // 获取序号 var allelement = this.id.getelementsbyclassname("item"); for(var i = 0; i < this.number-1; i++){ // 比较序号 if( this.numberarr[i].x != allelement[i].style.left || this.numberarr[i].y != allelement[i].style.top ){ return false; } } return true; }, } // 实例化一个对象 var box = new jigsawgame({ id: 'canvasbox', imgurl: '../image/lingtai.jpg', level: 1, gametype: 1 }); // 实例化一个对象 var box2 = new jigsawgame({ id: 'canvasbox2', imgurl: '../image/lingtai.jpg', level: 1, gametype: 2 }); function setgame(a, b){ document.getelementbyid("canvasbox").style.display = a; document.getelementbyid("canvasbox2").style.display = b; } setgame("block", "none");
稍微修改一下样式和触发事件,就是一个h5版本的demo。由于没用到项目里,没有考虑兼容问题
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。