2023年夏季《移动软件开发》实验报告
一、实验目标
1、综合所学知识创建完整的前端新闻小程序项目;2.能够在开发过程中熟练掌握真机预览、调试等操作。
二、实验步骤
1.创建项目
2.删除和修改模板文件
3.创建其他文件
(1)添加图片文件夹(images)和其内二级文件夹(icons)
(2)创建公共JS文件夹(utils)
4.根据个人喜好设置导航栏样式(app.json)
"window": {
"backgroundTextStyle": "light",
"navigationBarBackgroundColor": "#E64340",
"navigationBarTitleText": "推箱子游戏",
"navigationBarTextStyle": "white"
},
5.首页设计
<!--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}}'></image>
<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;
}
6.公共样式设计
/**app.wxss**/
.container {
height: 100%;
color:#E64340;
font-weight: bold;
display: flex;
flex-direction: column;
align-items: center;
justify-content: space-evenly;
}
.title{
font-size:18pt;
}
7.游戏界面设计
<!--pages/game/game.wxml-->
<view class='container'>
<!-- 关卡提示 -->
<view class='title'>第{{level}}关</view>
<!-- 游戏画布 -->
<canvas canvas-id='myCanvas'></canvas>
<!-- 方向键 -->
<view class='btnBox'>
<button type='warn' bindtap='up' size="mini">↑</button>
<view>
<button type='warn' bindtap='left' size="mini">←</button>
<button type='warn' bindtap='down' size="mini">↓</button>
<button type='warn' bindtap='right' size="mini">→</button>
</view>
</view>
<!-- “重新开始”按钮 -->
<button type='warn' bindtap='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:70rpx;
}
/* 所有按钮样式 */
button{
margin:10rpx;
}
8.首页逻辑实现
需要完成游戏选关和跳转到游戏界面的逻辑
Page({
/**
* 页面的初始数据
*/
data: {
levels:[
'level01.png',
'level02.png',
'level03.png',
'level04.png'
]
}
/**
* 自定义函数--游戏选关
*/
chooseLevel: function (e) {
let level=e.currentTarget.dataset.level;
wx.navigateTo({
url:'../game/game?level='+level
})
}
})
9.游戏界面逻辑实现
// pages/game/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
var data=require('../../utils/data.js')
Page({
/**
* 页面的初始数据
*/
data: {
level:1
},
/**
* 生命周期函数--监听页面加载
*/
onLoad(options) {
// 获取关卡
let level=options.level
// 更新页面关卡标题
this.setData({
level:parseInt(level)+1
})
// 创建画布上下文
this.ctx=wx.createCanvasContext('myCanvas')
// 初始化地图数据
this.initMap(level)
// 绘制画布内容
this.drawCanvas()
},
/**
* 自定义函数--初始化地图数据
*/
initMap:function(level) {
// 读取原始的游戏地图数据
let mapData = data.maps[level]
// 使用双重for循环记录地图数据
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循环绘制8*8的地图
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()
},
/**
* 自定义函数--方向键上
*/
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()
}
},
/**
* 自定义函数--方向键下
*/
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()
// 检查游戏是否成功
this.checkWin()
}
},
/**
*自定义函数--方向键左
*/
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()
// 检查游戏是否成功
this.checkWin()
}
},
/**
* 自定义函数--方向键:右
*/
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()
//检查游戏是否成功
this.checkWin()
}
},
/**
* 自定义函数--判断游戏是否成功
*/
isWin:function() {
// 使用双重for循环遍历整个数组
for(var i=0;i<8;i++)
{
for(var j=0;j<8;j++)
{
// 如果有箱子没在终点
if(box[i][j]==4 && map[i][j]!=3)
{
// 返回false,表示游戏尚未成功
return false
}
}
}
//返回true,表示游戏成功
return true
},
/**
* 自定义函数--游戏成功处理
*/
checkWin:function() {
if(this.isWin()){
wx.showModal({
title:'恭喜',
content:'游戏成功!',
showCancel:false
})
}
},
/**
* 自定义函数--重新开始游戏
*/
restartGame:function(){
// 初始化地图数据
this.initMap(this.data.level-1)
// 绘制画布内容
this.drawCanvas()
}
})
三、程序运行结果
1.首页
2.选择关卡进入游戏界面
3.用箭头按钮控制小鸟移动
4.重新开始游戏
5.游戏成功
四、问题总结与体会
这次试验我学会了更多编写小程序的知识,学会了公共JS文件应该怎么使用和更加复杂的逻辑实现。