一、实验目标
1、综合所学知识创建完整的推箱子游戏;2、能够在开发过程中熟练掌握真机预览、调试等操作。
二、实验步骤
准备工作
本次实验需要两个页面,分别为index(主页面)和game(游戏页面),因此需要在pages下创建两个文件夹,同时在根目录创建images文件夹并将下载好的图片粘贴进去,最后创建utils文件夹,并在utils文件夹下创建data.js文件。
视图设计
首先是修改导航栏:
因为index和game中都用到了container和title,因此这两个元素的属性定义在app.wxss中:
/**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: 25pt;
}
然后设计主页面:
<!--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="{{index}}">
<image src="/images/{{item}}" />
<text>第{{index + 1}}关</text>
</view>
</view>
</view>
/**index.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;
}
效果图如下:
然后设计游戏页面:
<!--pages/game/game.wxml-->
<view class="container">
<view class="title">第{{level}}关</view>
<canvas canvas-id="myCanvas"></canvas>
<view class="btnBox">
<button type="warn" bind:tap="up">↑</button>
<view>
<button type="warn" bind:tap="left">←</button>
<button type="warn" bind:tap="down">↓</button>
<button type="warn" bind:tap="right">→</button>
</view>
</view>
<button type="warn" bind:tap="restartGame">重新开始</button>
</view>
/* pages/game/game.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;
}
效果图如下:
逻辑实现
首先是utils/data.js,这个文件用来记录地图数据,包含了map1~map4的数据和一个数据出口module.exports
。
然后是主界面,主页面主要实现的是点击跳转的功能,先给index.wxml中的box元素增加bind:tap并在index.js中自定义了一个chooseLevel函数用于跳转:
chooseLevel:function(e){
let level = e.currentTarget.dataset.level
wx.navigateTo({
url: '../game/game?level='+level
})
},
最后是游戏页面,这一个页面需要实现多个功能,包括实现地图的显示、实现人物的移动、判断是否通关以及实现重新开始。
地图的显示
这一块需要在data中定义level
,在page函数外定义var map
,var box
,var w
,var row
,var col
、自定义初始化地图数据函数initMap用来根据data.js中的地图数据初始化地图、自定义绘制地图函数drawCanvas用来根据当前地图数据绘制地图、最后修改onLoad函数实现地图的显示:
initMap: function (level) {
let mapData = data.maps[level]
for (let i = 0; i < 8; i++) {
for (let 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 (let i = 0; i < 8; i++) {
for (let 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(options) {
let level = options.level
this.setData({
level: parseInt(level) + 1
})
this.ctx = wx.createCanvasContext('myCanvas')
this.initMap(level)
this.drawCanvas()
},
人物的移动
这一部分需要先给game.wxml中的↑←↓→分别给予bind:tap属性,并自定义up、
down、left、right函数,这里仅给出up函数,其余三个函数同理:
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()
this.checkWin() //该函数在下一部分定义
}
},
判断游戏成功
这一部分需要我们每行走一步就判断一次游戏是否成功,因此这里自定义两个函数isWin
通过遍历map判断是否成功,checkWin
用到了isWin函数判断游戏是否成功并在成功后弹出对话框,最后在移动函数中调用checkWin函数实现每走一步判断一次游戏是否成功。
isWin: function () {
for (let i = 0; i < 8; i++) {
for (let 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
})
}
},
重新开始游戏
游戏最下方的重新开始
按钮,点击后重置地图数据。因此先给按钮添加bind:tap属性,然后自定义restartGame函数即可:
restartGame: function () {
this.initMap(this.data.level - 1)
this.drawCanvas()
},