<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
本文範例為大家分享了用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。由於沒用到專案裡,沒有考慮相容問題
以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支援it145.com。
相關文章
<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
综合看Anker超能充系列的性价比很高,并且与不仅和iPhone12/苹果<em>Mac</em>Book很配,而且适合多设备充电需求的日常使用或差旅场景,不管是安卓还是Switch同样也能用得上它,希望这次分享能给准备购入充电器的小伙伴们有所
2021-06-01 09:31:42
除了L4WUDU与吴亦凡已经多次共事,成为了明面上的厂牌成员,吴亦凡还曾带领20XXCLUB全队参加2020年的一场音乐节,这也是20XXCLUB首次全员合照,王嗣尧Turbo、陈彦希Regi、<em>Mac</em> Ova Seas、林渝植等人全部出场。然而让
2021-06-01 09:31:34
目前应用IPFS的机构:1 谷歌<em>浏览器</em>支持IPFS分布式协议 2 万维网 (历史档案博物馆)数据库 3 火狐<em>浏览器</em>支持 IPFS分布式协议 4 EOS 等数字货币数据存储 5 美国国会图书馆,历史资料永久保存在 IPFS 6 加
2021-06-01 09:31:24
开拓者的车机是兼容苹果和<em>安卓</em>,虽然我不怎么用,但确实兼顾了我家人的很多需求:副驾的门板还配有解锁开关,有的时候老婆开车,下车的时候偶尔会忘记解锁,我在副驾驶可以自己开门:第二排设计很好,不仅配置了一个很大的
2021-06-01 09:30:48
不仅是<em>安卓</em>手机,苹果手机的降价力度也是前所未有了,iPhone12也“跳水价”了,发布价是6799元,如今已经跌至5308元,降价幅度超过1400元,最新定价确认了。iPhone12是苹果首款5G手机,同时也是全球首款5nm芯片的智能机,它
2021-06-01 09:30:45