本文实例为大家分享了用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
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 = {
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);
}
}
},
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
});
},
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;
},
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;
},
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)
},
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;
},
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
});
}
},
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;
},
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;
},
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);
},
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 ;
}
},
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。由于没用到项目里,没有考虑兼容问题
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持编程网。