一、实验目标
1、综合应用所学知识创建完整的拼图游戏项目;2、熟练掌握组件。
二、实验步骤
列出实验的关键步骤、代码解析、截图。
1.创建一个新的项目,同时新增images文件夹,将所需的图片放入其中。
2.关键代码
index.wxml
主页面的视图设计,主要是将六张图片摆放好,并赋上名字,标明是第几关。
<!--index.wxml-->
<view class="container">
<!--标题-->
<view class="title">游戏选关</view>
<!--关卡列表-->
<view class='levelBox'>
<view class="box" wx:for="{{levels}}" wx:key="levels{{index}}" bindtap="chooseLevel" data-level="{{item}}">
<image src="/images/{{item}}"></image>
<text>第{{index+1}}关</text>
</view>
</view>
</view>
index.js
主页面的逻辑实现,主要是要初始化数据,要让主页面有图片显示,第二就是要能够通过点击图片进入到游戏页面,通过chooseLevel函数来实现
// index.js
Page({
/**
* 页面的初始数据
*/
data: {
levels:[
'pic01.jpg',
'pic02.jpg',
'pic03.jpg',
'pic04.jpg',
'pic05.jpg',
'pic06.jpg'
]
},
/**
*
* 自定义函数,游戏选关
*/
chooseLevel:function(e) {
let level=e.currentTarget.dataset.level
wx:wx.navigateTo({
url: '../game/game?level='+level
})
},
})
game.wxml
游戏页面的视图设计,主要是有由主页面不同关卡点进来的关卡图片,还有由canvas组件组成的画布区域,绑定触摸画布的函数。
<!--pages/game/game.wxml-->
<view class="container">
<!--提示图区域-->
<view class="title">提示图</view>
<image src="{{url}}"></image>
<!--游戏画布-->
<canvas canvas-id="myCanvas" bindtouchstart='touchBox'></canvas>
<!--重新开始的按钮-->
<button type="warn" bindtap="restartGame">重新开始</button>
</view>
game.js
游戏页面的逻辑实现,最重要的有以下几个功能
(1)接受在主页面点击的关卡信息,成功跳转页面
(2)规划一片画布区域,drawCanvas将关卡图片信息赋在画布上,将挂关卡图片分成九个方块,并把(2,2)赋为空白方块
(3)shuffle函数,实现将九个方块(其中有一个空白方块)打乱
(4)touchBox和moveBox函数触摸方块并移动方块(能够移动的方块,它的周围一定是存在空白方块的)
(5)要存在一个判断是否将拼图拼好的isWin函数,成功则会显示图片,并出现一定的文字
(6)重新开始的按钮,也就是再次打乱方块
// pages/game/game.js
//方块的初始位置
var num=[
['00','01','02'],
['10','11','12'],
['20','21','22']
]
//方块的宽度
var w=100
//图片的初始地址
var url='/images/pic01.jpg'
Page({
/**
* 页面的初始数据
*/
data: {
isWin:false
},
/**
*
* 自定义函数--判断游戏是否成功
*/
isWin:function()
{
//使用双重for循环遍历整个数组
for(var i=0;i<3;i++)
{
for(var j=0;j<3;j++)
{
//如果有方块位置不对,则返回false
if(num[i][j]!=i*10+j)
{
return false
}
}
}
//更新游戏成功状态
this.setData({iswin:true})
return true
},
/**
* 生命周期函数--监听页面加载
*/
onLoad(options) {
//更新图片信息
url='/images/'+ options.level
//更新提示图片地址
this.setData({
url:url
})
//创建画布上下文
this.ctx=wx.createCanvasContext('myCanvas')
//打乱方块顺序
this.shuffle()
//绘制画布内容
this.drawCanvas()
},
/**
* 自定义函数--随机打乱方块顺序
*/
shuffle:function()
{
//先令所有方块回归原始位置
num=[
['00','01','02'],
['10','11','12'],
['20','21','22']
]
//记录当前空白方块的行和列
var row=2
var col=2
//打乱方块顺序100次
for(var i=0;i<100;i++)
{
//随机产生一个方向,上下左右,0123
var direction=Math.round(Math.random()*3)
//上:0
if(direction==0)
{
//空白方块不在最上面一行
if(row!=0)
{
//交换位置
num[row][col]=num[row-1][col]
num[row-1][col]='22'
//更新空白方块的行
row-=1
}
}
//下:1
else if(direction==1)
{
//空白方块不在最下面一行
if(row!=2)
{
//交换位置
num[row][col]=num[row+1][col]
num[row+1][col]='22'
//更新空白方块的行
row+=1
}
}
//左:2
else if(direction==2)
{
//空白方块不在最左侧
if(col!=0)
{
//交换位置
num[row][col]=num[row][col-1]
num[row][col-1]='22'
//更新空白方块的行
col-=1
}
}
//右:3
else if(direction==3)
{
//空白方块不在最右侧
if(col!=2)
{
//交换位置
num[row][col]=num[row][col+1]
num[row][col+1]='22'
//更新空白方块的行
col+=1
}
}
}
},
/**
* 自定义函数--绘制画布内容
*/
drawCanvas:function()
{
let ctx=this.ctx
//清空画布
ctx.clearRect(0,0,300,300)
//使用双重for循环绘制3*3的拼图
for(var i=0;i<3;i++)
{
for(var j=0;j<3;j++)
{
if(num[i][j]!='22')
{
//获取行和列
var row=parseInt(num[i][j]/10)
var col=num[i][j]%10
//绘制方块
ctx.drawImage(url,col*w,row*w,w,w,j*w,i*w,w,w)
}
}
}
ctx.draw()
},
/**
* 自定义函数--监听点击方块事件
*
*/
touchBox:function(e)
{
//如果游戏已经成功,不做任何操作
if(this.data.isWin)
{
return
}
//获取被点击的方块坐标
var x=e.changedTouches[0].x
var y=e.changedTouches[0].y
console.log('x:'+x+',y:'+y)
//换算成行和列
var row=parseInt(y/w)
var col=parseInt(x/w)
//如果点击的不是空白位置
if(num[row][col]!='22')
{
//尝试移动方块
this.moveBox(row,col)
//重新绘制画布内容
this.drawCanvas()
//判断游戏是否成功
if(this.isWin())
{
//在画面上绘制提示语句
let ctx=this.ctx
//绘制完整图片
ctx.drawImage(url,0,0)
//绘制文字
ctx.setFillStyle('#e64340')
ctx.setTextAlign('center')
ctx.setFontSize(60)
ctx.fillText('游戏成功',150,150)
ctx.draw()
}
}
},
/**
* 自定义函数--移动被点击的方块
*/
moveBox:function(i,j)
{
//情况1:如果被点击的方块不在最上方,检查是否可以上移
if(i>0)
{
//如果方块上面是空白
if(num[i-1][j]=='22')
{
//交换方块与空白的位置
num[i-1][j]=num[i][j]
num[i][j]='22'
return
}
}
//情况2:如果被点击的方块不在最下方,检查是否可以下移
if(i<2)
{
//如果方块下面是空白
if(num[i+1][j]=='22')
{
//交换方块与空白的位置
num[i+1][j]=num[i][j]
num[i][j]='22'
return
}
}
//情况3:如果被点击的方块不在最左侧,检查是否可以左移
if(j>0)
{
//如果方块左边是空白
if(num[i][j-1]=='22')
{
//交换方块与空白的位置
num[i][j-1]=num[i][j]
num[i][j]='22'
return
}
}
//情况4:如果被点击的方块不在最右侧,检查是否可以右移
if(j<2)
{
//如果方块右边是空白
if(num[i][j+1]=='22')
{
//交换方块与空白的位置
num[i][j+1]=num[i][j]
num[i][j]='22'
return
}
}
},
/**
* 自定义函数--重新开始游戏
*/
restartGame:function()
{
//更新游戏成功状态、
this.setData({isWin:false})
//打乱方块顺序
this.shuffle()
//绘制画布内容
this.drawCanvas()
},
4.最后的主页面和游戏页面
三、程序运行结果
列出程序的最终运行结果及截图。
初始页面
点击第二关的图片,跳转页面
然后点击根据提示图,点击图片,移动位置,将拼图拼完整,就会得到以下的结果。
同时,如果拼图太难或者已经拼图成功,可以点击重新开始,就会出现不一样的拼图顺序。
四、问题总结与体会
描述实验过程中所遇到的问题,以及是如何解决的。有哪些收获和体会,对于课程的安排有哪些建议。
总结:
1.方块点击后无法移动,经过检查,发现是this.drawCanvas()后面的括号忘加了。出现问题时候,可以根据错误的提示找到对应行数以及相关函数的代码进行检查。
2.明明代码没有错,但模拟器的图片大小不太对,可以看看左上角手机型号,不同手机型号,屏幕大小也不同
3.在创建画布上下文的时候,会出现this.ctx=wx.createCanvasContext(‘myCanvas’)这个语句中createCanvasContext被划掉的情况,经查询,wx.createCanvasContext已经被废弃了,但是目前使用起来并没有问题,于是也没有进行更改。
体会:
本次实验,熟悉了解了canvas组件,也巩固了前面学的小程序知识。