My sixth miniprogram~

一、实验目标

1、学习使用快速启动模板创建小程序的方法;2、学习不使用模板手动创建小程序的方法。

二、实验步骤

1.项目创建

首先在文件夹中加入以下所需文件。

2.代码解析

以下着重介绍wxml中对各容器类型的引用方式及js文件中页面的实现逻辑。

选关卡主页面

<!--pages/index/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>

此部分代码实现了关卡选择页面的页面排布,同时实现了根据关卡数量更新显示相对应数目及对应关卡地图、关卡数目的功能。用微信小程序自带的wx:for='{{levels}}' wx:key='levels{{index}}'实现所有关卡的显示;用内嵌的bindtap='chooseLevel'设置在点击时前往chooseLevel函数执行页面跳转。

// pages/index/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
      })
    },

此部分js文件实现了主页面的页面逻辑,data中的levels包含了所有关卡对应的封面页,同时界定chooseLevel函数用于实现对应关卡页面的跳转,其利用的是微信小程序自带的navigateTo函数。

关卡页面

<!--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>

此部分用于设置各个关卡页面的排布样式,利用<canvas>生成画布并给予其对应id名称。在button中定义type='warn'将按钮设置为红色,bingdtap实现点击后跳转对应函数执行。

var data = require("../../utils/data")
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)
    // 绘制地图
    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(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
      })
    }
    
  },
​
  restartGame: function () {
    this.initMap(this.data.level - 1)
    this.drawCanvas()
  },
​
  /**
   * 生命周期函数--监听页面加载
   */
  onLoad: function(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()
  },
​
​

此部分实现了游戏页面的信息数据初始化分别初始化地图格式、箱子数目及类型、主角所在位置。

initMap函数通过读取unils文件中的data.js读取对应关卡的地图格式、箱子数目及类型、主角所在位置。

drawCanvas初始化地图样式,设置箱子、小猪、石头和主角小鸟的样式,即完成了页面的UI排布。

up、down、left、right函数分别实现了上、下、左、右的行走及推动箱子。

isWin函数用于判断玩家是否成功将箱子推到小猪位置。

checkWin函数在调用isWin函数基础上实现与用户的交互输出游戏成功或失败。

三、程序运行结果

初始页面:

进入第二关后页面展示:

游戏通过后页面显示:

游戏进行重新开始后页面展示:

四、问题总结与体会

首先,由于微信小程序版本更新过快,在game.js的onLoad函数中我们使用wx.createCanvasContext(string)函数时会发现其可用版本低于2.9.0,而到目前最低可用版本为2.14.0,因此此处存在问题,但不影响使用。通过查阅Canvas文档发现可以将被弃用的wx.createCanvasContext(string)函数转为使用wx.createSelectQuery()进行context对象的获取。

其次,由于本人的一再粗心,竟然在<canvas></canvas>引用中错大canvas为convas从而导致画布无法正常生成,此为经常犯的错误,和上次将setData写作setDate一样为使用不熟练的问题,以后将更加注意。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值