小程序:推箱子游戏

一、实验目标

1、综合应用所学的知识创建完整的推箱子游戏。

2、熟练掌握canvas和绘图API。

二、实验步骤

2.1 项目准备

  1. 创建项目并创建游戏页面(将app.json文件内pages属性中的“pags/logs/logs改成“pages/game/game”,ctrl+S保存)。
  2. 删除utils和logs目录及其内部所有内容。
  3. 删除index.wxml、index.wxss和app.wxss全部代码。
  4. 删除index.js和app.js中全部代码。并分别输入page和app回车补全函数。

2.2 页面设计

  1. 在app.wxss中设置页面窗口和顶端标题的公共样式
  2. 顶端标题:view容器;关卡列表:view容器,内部使用数组循环。
  3. 效果如图所示,具体代码见2.4。

请添加图片描述

  1. 游戏页面设计view,整体容器和顶端标题;canvas,游戏画布。具体代码见2.4。

请添加图片描述

2.3 逻辑实现

2.3.1 公共逻辑和首页逻辑

功能实现:展示关卡列表

  1. 在utils/data.js中配置游戏地图的数据,使用module.exports语句暴露数据接口。

  2. index.js中data 录入关卡图片的数据信息

  3. 关卡对应的view组件添加wx:for属性循环显示关卡列表数据和图片。

  4. 为关卡列表项目添加点击事件。利用bindtap绑定chooseLevel函数,并且使用data-level属性携带关卡图片下标信息。

  5. 效果如图所示,相关代码件2.4代码。
    请添加图片描述

2.3.2 游戏页逻辑

功能实现:显示当前是第几关;游戏地图的绘制;4个方向键可以移动游戏主角;点击重新开始按钮可以是游戏页面还原为最初状态。

  1. 显示提示图。首页逻辑中已经实现页面跳转并携带关卡对应的图片信息,游戏页面需接收关卡信息,并显示对应的图片内容。此时从首页点击不同的关卡图片就可以实现跳转。

  2. 游戏逻辑实现。首先在game.js文件的顶端记录一些游戏初始数据信息。其后,初始化游戏画面。首先根据当前第几关读取对应游戏信息,并更新到初始游戏数据中。在game.js中添加initMap函数,用于初始化游戏地图数据;添加自定义函数drawCanvas,用于地图信息绘制到画布上;在onLoad函数中调用自定义函数initMap和drawCanvas。

请添加图片描述

  1. 绑定方向键。修改game.wxml页面中的4个方向键,为其绑定点击事件。在game.js文件添加自定义函数up,down,left,right,用于实现小鸟的移动。

  2. 在game.js文件中的data中添加自定义函数isWin,用于判断游戏成功与否。添加自定义函数checkWin,要求一旦游戏成功就弹出游戏提示对话框。

  3. 重新开始游戏,添加自定义restartGame函数,用于重新开始游戏。具体代码见2.4。

2.4 代码

2.4.1 html
<!--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="chooseLevel" data-level = '{{index}}'>
            <image src="/images/{{item}}" mode=""/>
            <text>第{{index+1}}关</text>
        </view>
    </view>
</view>
<!--pages/game/game.wxml-->
<view class="container">
    <view class="title">游戏选关</view>
    <view class="levelBox">
        <view class="box" wx:for="{{levels}}" wx:key="levels{{index}}" bind:tap="chooseLevel" data-level = '{{index}}'>
            <image src="/images/{{item}}" mode=""/>
            <text>第{{index+1}}关</text>
        </view>
    </view>
</view>
2.4.2 css
/* pages/index/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.wxss */
canvas{
  border: 1rpx solid;
  width: 304px;
  height: 304px;
}

.btnBox{
  display: flex;
  flex-direction: column;
  align-items: center;
}

.btnBox view{
  display: flex;
  flex-direction: row;
}

.btnBox button{
  height: 38px;
}

button{
  margin: 10rpx;
}
2.4.3 js
// 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,
    })
  }
    /**
   * 系统默认函数省略
   */
})

// pages/game/game.js
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 = 38
var row = 0
var col = 0
Page({

  /**
   * 页面的初始数据
   */
  data: {
    level:1,
    ctx:"",
  },
  initMap:function(level){
    let mapData = data.maps[level]
    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(options) {
    let level = options.level
    this.setData({
      level:parseInt(level)+1
    })
    this.ctx = wx.createCanvasContext('myCanvas')
    this.initMap(level)
    this.drawCanvas()
  }
     /**
   * 系统默认函数省略
   */
})
// utils/data.js
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]
  ]
  
  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]
  ]
  
  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]
  ]
  
  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]
}

三、程序运行结果

  1. 以第二关为例,进入第二关后,页面效果如下,使用方向按钮控制小鸟推动箱子。
    请添加图片描述

  2. 箱子全部盖住小猪后,弹出游戏成功面板,效果如下所示。

请添加图片描述

  1. 如若像重开游戏,点击重新开始,刷新页面,效果如下。

请添加图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值