一、实验目标
1、综合所学知识创建完整的推箱子游戏;
2、能够在开发过程中熟练掌握真机预览、调试等操作。
二、实验步骤
1.公共设计
1.1导航栏设计
在app.json中添加以下代码,将导航栏修改为红色背景,白色字体的效果:
"window": { "navigationBarBackgroundColor": "#E64340", "navigationBarTitleText": "推箱子游戏" },
效果如图:
1.2公共样式设计
在app.wxss设置公共的样式,减少代码的冗余,增加其复用性,写入以下代码:
.container{ height: 100vh; color: #E64340; font-weight: bold; display: flex; flex-direction: column; align-items: center; justify-content: space-evenly; } .title{ font-size: 18pt; }
2.页面设计
2.1首页设计
首页主要包括标题和关卡列表,这里使用view组件来构建整个页面,在.wxml中写入以下代码:
<view class='container'> <view class='title'>游戏选关</view> <view class='levelBox'> <view class="box"> <image src="/images/level01.png"/> <text>第一关</text> </view> </view> </view>
在.wxss文件中为其添加样式:
.levelBox{ width: 100%; } .box{ width: 50%; float: left; margin: 20rpx 0; display: flex; flex-direction: column; align-items: center; } image{ width: 300rpx; height: 300rpx; }
当前页面如图所示:
2.2游戏页面设计
游戏页面共有四个组成部分:标题,游戏区域,方向键和重新开始按钮。
由于还未在首页设置跳转函数,因此需要通过添加编译模式来预览游戏页面的效果:
然后开始构建页面,首先在game.wxml中写入以下代码:
<view class='container'> <view class='title'>第一关</view> <canvas canvas-id="myCanvas"/> <view class='btnBox'> <button type="warn">↑</button> <view> <button type="warn">←</button> <button type="warn">↓</button> <button type="warn">→</button> </view> </view> <button type="warn">重新开始</button> </view>
在.wxss中设置样式:
canvas{ border: 1rpx solid; width: 320px; height: 320px; } .btnBox{ display: flex; flex-direction: column; align-items: center; } .btnBox view{ display: flex; flex-direction: row; } .btnBox button{ width: 90rpx; height: 90rpx; } button{ margin: 10rpx; }
此时的效果如下图所示:
3.逻辑实现
3.1公共逻辑
在utils文件下新建一个data.js文件,用于存储游戏的地图数据等公共数据,在其中写入以下代码:
var map1 = [ [0,1,1,1,1,1,0,0], [0,1,2,2,1,1,1,0], [0,1,5,4,2,2,1,0], [1,1,1,2,1,2,1,1], [1,3,1,2,1,2,2,1], [1,3,4,2,2,1,2,1], [1,3,2,2,2,4,2,1], [1,1,1,1,1,1,1,1] ] var map2 = [ [0,0,1,1,1,0,0,0], [0,0,1,3,1,0,0,0], [0,0,1,2,1,1,1,1], [1,1,1,4,2,4,3,1], [1,3,2,4,5,1,1,1], [1,1,1,1,4,1,0,0], [0,0,0,1,3,1,0,0], [0,0,0,1,1,1,0,0] ] var map3=[ [0,0,1,1,1,1,0,0], [0,0,1,3,3,1,0,0], [0,1,1,2,3,1,1,0], [0,1,2,2,4,3,1,0], [1,1,2,2,5,4,1,1], [1,2,2,1,4,4,2,1], [1,2,2,2,2,2,2,1], [1,1,1,1,1,1,1,1] ] var map4=[ [0,1,1,1,1,1,1,0], [0,1,3,2,3,3,1,0], [0,1,3,2,4,3,1,0], [1,1,1,2,2,4,1,1], [1,2,4,2,2,4,2,1], [1,2,1,4,1,1,2,1], [1,2,2,2,5,2,2,1], [1,1,1,1,1,1,1,1] ] module.exports={ maps:[map1,map2,map3,map4] }
其中,地图中1代表墙,2代表道路,3代表终点,4代表箱子,5代表人物,6代表地图外围。
之后需要在其他页面中引用该文件,在game.js页面的顶部添加以下代码:
var data=require('../../utils/data.js')
3.2关卡展示与跳转
首先在index.js文件中写入以下数据:
data: { levels:[ 'level101.png', 'level102.png', 'level103.png', 'level104.png', ] },
用于记录图片的信息。
接下来修改view组件,通过wx:for循环显示关卡数据:
<view class="box" wx:for="{{levels}}" wx:key="levels{{index}}"> <image src="/images/{{item}}"/> <text>第{{index+1}}关</text>
此时程序的效果如图:
然后继续修改.wxml文件,为其添加点击事件,实现点击后跳转关卡的功能:
<view class="box" wx:for="{{levels}}" wx:key="levels{{index}}" bind:tap="chooseLevel" data-level='{{index}}'>
接下来就要在js文件中添加相应的相应函数:
chooseLevel:function(e){ let level = e.currentTarget.dataset.level wx.navigateTo({ url: '../game/game?level='+level, }) },
现在就可以实现点击关卡的跳转功能了。
3.3游戏逻辑实现
首先修改game.js文件,加入level数据,来显示当前游戏为第几关,在data内加入level属性,并且在OnLoad函数中接受跳转页面时传递来的参数,使用setData将level设置为接受到的参数:
onLoad(options) { let level=options.level this.setData({ level:parseInt(level)+1 }) },
修改.wxml文件,使其动态显示关卡数:
<view class='title'>第{{level}}关</view>
此时点击不同的关卡就会跳转到不同的页面了:
之后开始进行最重要的一部分,也就是游戏运行的逻辑,首先在game.js文件中添加以下数据:
var map=[ [0,0,0,0,0,0,0,0], [0,0,0,0,0,0,0,0], [0,0,0,0,0,0,0,0], [0,0,0,0,0,0,0,0], [0,0,0,0,0,0,0,0], [0,0,0,0,0,0,0,0], [0,0,0,0,0,0,0,0], [0,0,0,0,0,0,0,0] ] var box=[ [0,0,0,0,0,0,0,0], [0,0,0,0,0,0,0,0], [0,0,0,0,0,0,0,0], [0,0,0,0,0,0,0,0], [0,0,0,0,0,0,0,0], [0,0,0,0,0,0,0,0], [0,0,0,0,0,0,0,0], [0,0,0,0,0,0,0,0] ] var w=40 var row=0 var col=0
然后在其中添加一个初始化函数,用来读取地图数据,在js文件添加以下代码:
initMap:function(level){ let mapData=data.maps[level] for(var i=0;i<8;i++){ for(var j=0;j<8;j++){ box[i][j]=0 map[i][j]=mapData[i][j] if(mapData[i][j]==4){ box[i][j]=4 map[i][j]=2 }else if(mapData[i][j]==5){ map[i][j]=2 row=i col=j } } } },
之后继续添加自定义函数,绘制画布:
drawCanvas:function(){ let ctx=this.ctx ctx.clearRect(0,0,320,320) for(var i=0;i<8;i++){ for(var j=0;j<8;j++){ let img='ice' if(map[i][j]==1){ img='stone' }else if(map[i][j]==3){ img='pig' } ctx.drawImage('/images/icons'+img+'.png',j*w,i*w,w,w) if(box[i][j]==4){ ctx.drawImage('/images/icons/box.png',j*w,i*w,w,w) } } } ctx.drawImage('/images/icons/bird.png',col*w,row*w,w,w) ctx.draw() },
最后只需在OnLoad函数中依次调用自定义的函数,即可实现整个游戏地图的加载和绘制:
onLoad(options) { let level=options.level console.log(options.level) this.setData({ level:parseInt(level)+1 }) this.ctx=wx.createCanvasContext('myCanvas') this.initMap(level) this.drawCanvas() },
现在就可以有整个画面了:
但是现在也仅仅只是有画面,并不能进行人物的移动,因此现在来为四个方向健添加点击事件:
<button type="warn" bind:tap="up">↑</button> <button type="warn" bind:tap="left">←</button> <button type="warn" bind:tap="down">↓</button> <button type="warn" bind:tap="right">→</button>
然后在,js文件中添加对应的函数,来实现人物的移动:
up:function(){ if(row>0){ if(map[row-1][col]!=1 && box[row-1][col]!=4){ row=row-1 } else if(box[row-1][col]==4){ if(row-1>0){ if(map[row-2][col]!=1&&box[row-2][col]!=4){ box[row-2][col]=4 box[row-1][col]=0 row=row-1 } } } this.drawCanvas() } }, down:function(){ if(row<7){ if(map[row+1][col]!=1 && box[row+1][col]!=4){ row=row+1 } else if(box[row+1][col]==4){ if(row+1<7){ if(map[row+2][col]!=1&&box[row+2][col]!=4){ box[row+2][col]=4 box[row+1][col]=0 row=row+1 } } } this.drawCanvas() } }, left:function(){ if(col>0){ if(map[row][col-1]!=1 && box[row][col-1]!=4){ col=col-1 } else if(box[row][col-1]==4){ if(col-1>0){ if(map[row][col-2]!=1&&box[row][col-2]!=4){ box[row][col-2]=4 box[row][col-1]=0 col=col-1 } } } this.drawCanvas() } }, right:function(){ if(col<7){ if(map[row][col+1]!=1 && box[row][col+1]!=4){ col=col+1 } else if(box[row][col+1]==4){ if(col+1<7){ if(map[row][col+2]!=1&&box[row][col+2]!=4){ box[row][col+2]=4 box[row][col+1]=0 col=col+1 } } } this.drawCanvas() } },
现在人物已经可以移动了,也能够推箱子,接下来进行游戏成功的判定。
在js文件中添加以下函数在判断游戏是否成功:
isWin:function(){ for(var i=0;i<8;i++){ for(var j=0;j<8;j++){ if(box[i][j]==4&&map[i][j]!=3){ return false } } } return true },
之后继续添加函数,调用判断函数并弹出提示框:
checkWin:function(){ if(this.isWin()){ wx.showModal({ title: '恭喜', content: '游戏成功', showCancel:false }) } },
然后将这个函数添加到方向键的相应函数,这样每次点击移动一次,就会判断这一次移动以后游戏是否成功,在四个函数的最后均加入以下语句:
this.checkWin()
这样游戏就可以顺利进行了。
最后需要为重新开始按钮添加响应事件:
<button type="warn" bind:tap="restartGame">重新开始</button>
添加对应函数:
restartGame:function(){ this.initMap(this.data.level-1) this.drawCanvas() },
至此,所有的功能都实现完成。
三、程序运行结果
首页:
游戏页面:
游戏成功: