姓名? | 王建享 |
---|---|
本实验属于哪门课程? | 中国海洋大学24夏《移动软件开发》 |
实验名称? | 实验6:推箱子游戏 |
博客地址? | 2024年夏季《移动软件开发》实验6报告 |
Gitee仓库地址? | miniSokobanApp |
一、实验目标
1、综合所学知识创建完整的推箱子游戏;2、能够在开发过程中熟练掌握真机预览、调试等操作。
二、实验步骤
创建一个微信小程序
添加页面组件
<!--pages/index/index.wxml--> <view class='container'> <view class='title'>选择关卡</view> <view class='levelBox'> <view class='box' wx:for="{{levels}}" wx:key="levels{{index}}" bind:tap="toGame" data-level="{{index}}"> <image src='/images/{{item}}'/> <text>第{{index + 1}}关</text> </view> </view> </view> <!--pages/game/game.wxml--> <view class="container"> <view class='title'>第{{level}}关</view> <canvas canvas-id="sokoban"></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="restart">重新开始</button> </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; } /**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; } /**app.wxss**/ .container { height: 100vh; color: #e64340; display: flex; flex-direction: column; font-weight: bold; align-items: center; justify-content: space-evenly; } .title{ font-size: 18pt; }
编写页面逻辑
index跳转至game页面并传递level参数
toGame:(event)=>{ let level = event.currentTarget.dataset.level; wx.navigateTo({ url: '../game/game?level=' + level, }) },
根据level参数初始化地图数据
initMap(level){ let allMap = data.maps[level] for(var i = 0;i < 8;i++){ for(var j = 0;j < 8;j++){ box[i][j] = 0; map[i][j] = allMap[i][j]; if(allMap[i][j] == 4){ box[i][j] = 4; map[i][j] = 2; }else if(allMap[i][j] == 5){ map[i][j] = 2; row = i; col = j; } } } },
根据地图在画布中绘制相应图片
drawMap(){ 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/' + img + '.png', j * w, i * w, w, w) if(box[i][j] == 4){ ctx.drawImage('/images/box.png', j * w, i * w, w, w) } } } ctx.drawImage('/images/bird.png',col * w, row * w, w, w) ctx.draw(); },
加载页面时获取传递的level参数并初始化地图数据
onLoad(options) { let level = options.level; this.setData({ level:parseInt(level) + 1 },()=>{ this.ctx = wx.createCanvasContext('sokoban') this.initMap(level) this.drawMap() }) },
移动主角,向左右下与向上同理,先判断前方是否有物体,若无则可直接移动,否则判断前方是否为箱子,若是箱子则判断其是否可以被推动,可以推动则将箱子和主角移动。所有判断完成后重新绘制地图数据并且检查是否达成胜利条件。
up(){ if(row > 0){ if(map[row - 1][col] != 1 && box[row - 1][col] != 4){ 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 -= 1 } } } } this.drawMap(); this.checkWin(); },
检查胜利条件,遍历所有地图上的点,若是箱子则判断其是否在终点之中,若全部在终点则返回胜利
isWin(){ 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(){ if(this.isWin()){ wx.showModal({ title: '恭喜', content: '你获得了胜利', showCancel:false }) } },
新开始函数,重新初始化地图数据并重新绘制地图
restart(){ this.initMap(this.data.level - 1); this.drawMap(); },
三、程序运行结果
四、实验总结与体会
本次实验编写了一个推箱子游戏的微信小程序,得益于前面5次实验的积累学习,本次实验进行得相当顺利,基本上没有遇到什么问题,使用到的组件,除了画布之外,其他基本上也都是之前实验已经使用过的组件。实验中使用到的createCanvasContext函数,在基础库2.9.0版本便已经停止维护了,但是这并不影响其被使用,值得注意的是,新版本中用于代替这个函数的API相比这个函数要复杂许多,不知道为什么要用一个复杂的API来代替原本清晰且简单易懂的API。