一、实验目标
1、综合所学知识创建完整的前端新闻小程序项目;能够在开发过程中熟练掌握真机预览、调试等操作。
二、实验步骤
列出实验的关键步骤、代码解析、截图。
1.创建小程序,在目录下创建images文件夹和utils文件夹,并将所需要的图片放入文件夹中,创建game页面
2.在utils文件夹下创建data.js文件,在里面存储地图数据,并让它对外开放
//==============================
//地图数据map1-map4
//地图数据:1为墙,2为路,3为终点,4为箱子,5为人物,0为墙的外围
//===============================
//关卡1
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]
]
//关卡2
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]
]
//关卡3
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]
]
//关卡4
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]
}
3.关键代码
导航栏的设计和公共样式
app.json
{
"pages": [
"pages/index/index",
"pages/game/game"
],
"window": {
"navigationBarBackgroundColor": "#90ac16",
"navigationBarTitleText": "推箱子游戏",
"navigationBarTextStyle": "black"
}
}
app.wxss
/**app.wxss**/
/*页面容器样式*/
.container {
height: 100vh;
color:#90ac16;
font-weight: bold;
display: flex;
flex-direction: column;
align-items: center;
justify-content: space-evenly;
}
/*顶端标题样式*/
.title{
font-size: 18pt;
}
主页页面设计,要有标题“游戏选关”以及下方四个关卡和图片
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="{{index}}">
<image src="/images/{{item}}"></image>
<text>第{{index+1}}关</text>
</view>
</view>
</view>
页面样式设计
index.wxss
/**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;
}
主页面逻辑实现,最主要的就是循环实现每一关图片,以及页面跳转
// index.js
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
})
}
})
游戏页面的设计
上面要能显示选的第几关以及选的关卡图片,以及方向键和重新开始的按钮
game.wxml
<!--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">↑</button>
<view>
<button type="warn" bindtap="left">←</button>
<button type="warn" bindtap="down">↓</button>
<button type="warn" bindtap="right">→</button>
</view>
</view>
<!--重新开始按钮-->
<button type="warn" bindtap="restartGame">重新开始</button>
</view>
游戏页面样式
game.wxss
/* 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;
}
游戏页面的逻辑实现
(1)要能够接收页面跳转的信息
(2)将图片信息写在画布上
(3)对于方向键的实现
(4)重新开始按钮的实现
(5)游戏成功的判断
因为会用到data.js里面的数据,需要在开头写上var data=require(‘…/…/utils/data.js’)
game.js
// pages/game/game.js
var data=require('../../utils/data.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
Page({
/**
* 页面的初始数据
*/
data: {
level:1
},
/**
*
* 自定义函数--初始化地图数据
*/
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)
//绘制8x8的地图
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()
}
},
/**
* 生命周期函数--监听页面加载
*/
onLoad(options) {
//获取关卡
let level=options.level
//更新页面关卡标题
this.setData({
level:parseInt(level)+1
})
//创建画布上下文
this.ctx=wx.createCanvasContext('myCanvas')
//初始化地图数据
this.initMap(level)
//绘制画布内容
this.drawCanvas()
},
/**自定义函数--判断游戏是否成功 */
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
}
}
}
return true
},
/**
* 自定义函数-- 游戏成功处理
*/
checkWin:function()
{
if(this.isWin())
{
wx.showModal({
title: '恭喜',
content: '游戏成功',
showCancel:false
})
}
},
/**
* 自定义函数--重新开始游戏
*/
restartGame:function()
{
//初始化地图数据
this.initMap(this.data.level-1)
//绘制画布内容
this.drawCanvas()
}
})
三、程序运行结果
列出程序的最终运行结果及截图。
初始页面:
选择关卡点进去:
移动小鸟去推动箱子:
移动成功后的页面:
当发现走错了以后,可以点击重新开始重来
四、问题总结与体会
描述实验过程中所遇到的问题,以及是如何解决的。有哪些收获和体会,对于课程的安排有哪些建议。
总结:
总的来说根据老师给的代码来写问题是不大的,最重要的就是要仔细,不要拼写错误,以及在写方向键的时候,加减符号以及数字都要注意。
体会:
本次实验让我使用了解熟悉了canvas组件,并且还把前面的知识巩固了。