2023年夏季《移动软件开发》实验报告
一、实验目标
1、综合应用所学知识创建完整的拼图游戏项目;2、熟练掌握组件。
二、实验步骤
1.创建小程序项目
2.由于小游戏需要有首页和游戏页面,所以我们需要创建游戏页面:将将app.json文件内pages属性中的“pags/logs/logs改成“pages/game/game”,并保存
3.删除不必要的默认文件和函数
4.创建images文件夹,并将关卡页面粘贴到此文件夹目录下
5.在app.json文件中设计导航栏颜色为珊瑚红色,标题为“拼图游戏”
6.首页页面设计:在pages/index/index.wxml文件中,我们将页面分为两大区域:标题和关卡列表,关卡列表我们用wx:for实现,并为每一关卡添加image组件用来显示每一关卡的图片,并在pages/index/index.wxss文件中设置相应的格式
7.游戏页面设计:在pages/game/game.wxml文件中,我们将页面分为三大区域:提示图区域、游戏画布和关卡按钮。其中,游戏画布我们用canvas组件实现。然后在pages/game/game.wxss文件中设置相应的格式
8.逻辑设计:在pages/index/index.js文件中添加chooseLevel函数实现点击首页不同关卡对应跳转至相应关卡的功能;在pages/game/game.js文件中添加shuffle函数实现打乱图片方块的功能,添加drawCanvas函数实现将打乱后的图形方块绘制到画布上的功能,添加touchBox函数实现图形方块的移动功能,添加isWin函数用来判断游戏是否成功,添加restartGame函数用来实现重新开始游戏功能
9.各文件代码如下:
app.json文件
{
"pages":[
"pages/index/index",
"pages/game/game"
],
"window":{
"navigationBarBackgroundColor": "#E64340",
"navigationBarTitleText": "拼图游戏"
},
"style": "v2",
"sitemapLocation": "sitemap.json"
}
pages/index/index.js文件
// 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.navigateTo({
url: '../game/game?level='+level
})
},
/**
* 生命周期函数--监听页面加载
*/
onLoad: function (options) {
},
/**
* 生命周期函数--监听页面初次渲染完成
*/
onReady: function () {
},
/**
* 生命周期函数--监听页面显示
*/
onShow: function () {
},
/**
* 生命周期函数--监听页面隐藏
*/
onHide: function () {
},
/**
* 生命周期函数--监听页面卸载
*/
onUnload: function () {
},
/**
* 页面相关事件处理函数--监听用户下拉动作
*/
onPullDownRefresh: function () {
},
/**
* 页面上拉触底事件的处理函数
*/
onReachBottom: function () {
},
/**
* 用户点击右上角分享
*/
onShareAppMessage: function () {
}
})
pages/index/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>
pages/index/index.wxss文件
/**index.wxss**/
.levelBox{
width:100%
}
.box{
width: 50%;
float: left;
margin:25rpx 0;
display: flex;
flex-direction: column;
align-items: center;
}
image{
width:260rpx;
height:260rpx;
}
pages/game/game.js文件
// 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(var i=0;i<3;i++){
for(var j=0;j<3;j++){
if(num[i][j]!=i*10+j){
return false
}
}
}
this.setData({isWin:true})
return true
},
shuffle:function(){
num=[['00','01','02'],['10','11','12'],['20',+'21','22']]
var row=2
var col=2
for(var i=0;i<100;i++){
var direction=Math.round(Math.random()*3)
//上
if(direction==0){
if(row!=0){
num[row][col]=num[row-1][col]
num[row-1][col]='22'
row-=1
}
}
//下
else if(direction==1){
if(row!=2){
num[row][col]=num[row+1][col]
num[row+1][col]='22'
row+=1
}
}
//左
else if(direction==2){
if(col!=0){
num[row][col]=num[row][col-1]
num[row][col-1]='22'
col-=1
}
}
//右
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(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
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){
if(i>0){
if(num[i-1][j]=='22'){
num[i-1][j]=num[i][j]
num[i][j]='22'
return
}
}
if(i<2){
if(num[i+1][j]=='22'){
num[i+1][j]=num[i][j]
num[i][j]='22'
return
}
}
if(j>0){
if(num[i][j-1]=='22'){
num[i][j-1]=num[i][j]
num[i][j]='22'
return
}
}
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()
},
/**
* 生命周期函数--监听页面加载
*/
onLoad:function(options) {
url='/images/'+options.level
this.setData({url:url})
this.ctx=wx.createCanvasContext('myCanvas')
this.shuffle()
this.drawCanvas()
},
/**
* 生命周期函数--监听页面初次渲染完成
*/
onReady() {
},
/**
* 生命周期函数--监听页面显示
*/
onShow() {
},
/**
* 生命周期函数--监听页面隐藏
*/
onHide() {
},
/**
* 生命周期函数--监听页面卸载
*/
onUnload() {
},
/**
* 页面相关事件处理函数--监听用户下拉动作
*/
onPullDownRefresh() {
},
/**
* 页面上拉触底事件的处理函数
*/
onReachBottom() {
},
/**
* 用户点击右上角分享
*/
onShareAppMessage() {
}
})
pages/game/game.wxml文件
<!--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>
pages/game/game.wxss文件
/* pages/game/game.wxss */
image{
width:250rpx;
height:250rpx;
}
canvas{
border:1rpx solid;
width: 300px;
height: 300px;
}
三、程序运行结果
四、问题总结与体会
通过本次实验,学会了简单的拼图游戏的制作,了解了canvas组件的使用,熟练了按钮点击事件的格式和循环的使用,认识了data-level属性和parseInt以及drawImage等方法,体味到了小程序小游戏制作的乐趣。