0基础开发第六个微信小程序:推箱子游戏

一、程序运行结果

在这里插入图片描述
在这里插入图片描述

二、实验目标

1、综合应用所学的知识创建完整的推箱子游戏;2、熟练掌握 和绘图 API。
3、自己设计额外功能:计分

三、实验步骤

1.创建项目,修改app.json中的pages:

{
  "pages": [
    "pages/index/index",
    "pages/game/game"
  ],

ctrl+s保存即可

2.删除模板中自带的多余的代码

在这里插入图片描述

3.创建images文件夹,右键在资源文件中打开,复制粘贴图片素材(https://gaopursuit.oss-cn-beijing.aliyuncs.com/course/mobileDev/boxgame_images.zip)

创建utils文件夹,新建data.js文件

4.导航栏设计:

在app.json中:

 "window": {
    "navigationBarTextStyle": "black",
    "navigationBarTitleText": "推箱子",
    "navigationBarBackgroundColor": "#E64340"
  },

在这里插入图片描述

5.公共页面与首页设计:

在app.wxss中:

/**app.wxss**/
.container {
  height: 100vh;
  color:#E64340;
  font-weight: bold;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: space-between;

} 

在index.wxml中设计首页布局:

<view class="container">
  <view class="title">游戏选关</view>
  <view class="levelBox">
    <view class="box">
      <image src="/images/level01.png"></image>
    </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.游戏页面设计:

由于暂时没有做跳转至游戏页面的逻辑,于是我们可以调整编译模式,从“普通编译”转为“添加编译模式”,调整启动页面和启动参数如下:

在这里插入图片描述

设计游戏页面布局:

在game.wxml中:

<!--pages/game/game.wxml-->
<view class='container'>
<!--关卡提示-->
<view class='title'>第1关</view>
<!--游戏画布-->
<canvas canvas-id='myCanvas'></canvas >
<!--方向键-->
<view class ='btnBox'>
  <button type= 'warn'>↑</button >
  <view>
    <button type = 'warn'>←</button >
    <button type = 'warn'>↓</button >
    <button type = 'warn'>→</button >
  </view >
</view>
  <!--重新开始-->
  <button type= 'warn'>重新开始</button >
</view>

在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;
}

编译运行如下:

在这里插入图片描述

7.公共逻辑实现:

在utils.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]
  }
  

最后在game.js中引用公共js文件,代码 为:

var data= require('../../utils/data.js')

8.首页逻辑实现:

展示关卡列表:在index.js中:

 data: {
    levels:[
      'level01.png',
      'level02.png',
      'level03.png',
      'level04.png',
    ]
  },

在idnex.wxml中:

<view class="container">
  <view class="title">游戏选关</view>
  <view class="levelBox">
    <view class="box" wx:for='{{levels}}'wx:key='levels{{index}}'>
      <image src='/images/{{item}}'></image>
      <text>第{{index+1}}关</text>
    </view>
  </view>
  
</view>

编译运行效果如下:

在这里插入图片描述

点击跳转功能逻辑实现:

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

在js文件中实现函数:

chooseLevel:function(e){
  let level=e.currentTarget.dataset.level
  wx.navigateTo({
    url:'../game/game?level='+level
  })
},

在game.js中接受图片信息:

  data: {
    level:1
  },

  /**
   * 生命周期函数--监听页面加载
   */
  onLoad:function(options) {
let level=options.level
this.setData({
  level:parseInt(level)+1
})
  },

在wxml中修改布局,设计关卡提示:

<!--pages/game/game.wxml-->
<view class='container'>
<!--关卡提示-->
<view class='title'>第{{level}}关</view>
<!--游戏画布-->

编译运行结果如下:

在这里插入图片描述
在这里插入图片描述

9.游戏逻辑实现:

在game.js中保存一些初始数据,设计初始化函数,绘制地图函数,并在onload函数中调用:

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
  },

  /**
   * 生命周期函数--监听页面加载
   */
  onLoad: function(options) {
    let level=options.level
    console.log('Received level:', level);

    this.setData({
      level:parseInt(level)+1
    })
    this.ctx=wx.createCanvasContext('myCanvas')
    this.initMap(this.data.level-1)
    this.drawCanvas()
  },

  initMap:function(level) {
    let mapData = data.maps[level];
    if (!mapData || !Array.isArray(mapData) || mapData.length < 8 || !Array.isArray(mapData[0])) {
        console.error('Invalid map data for level:', level);
        return;
    }

    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()
  },


编译运行结果如下:

在这里插入图片描述

10.方向键逻辑实现:

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

</view>

在js中设计对应的逻辑:

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()
 
    }
  },
  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()
 
    }
  },
  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()

    }
  },

  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()
 
    }
  },


11.游戏胜负检验逻辑:

在js文件中设计检验函数并在上下左右四个函数中调用(这里只写了up函数的例子):

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
      })
    }
  },
  
  

  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()
    }
  },
  

12.重新开始功能的逻辑实现:

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

在js中实现逻辑:

  restartGame:function(){
    this.initMap(this.data.level - 1)
    this.drawCanvas()
  },

OK,到这里功能就全部实现完了

四、问题总结与体会

​ 通过本次实验,我受益匪浅,切身体会了一个游戏制作过程的各种逻辑交互以及画面的修改绘制,还有各个页面的美化与布局,大大提高了我的动手能力。即便是一个简单的推箱子,想要实现也需要莫大的努力,今后我更应该努力提高自己。

​ 额外功能,我增加了计数功能,实时记录玩家的得分状况,下面是部分代码示例:

Page({

  /**
   * 页面的初始数据
   */
  data: {
    level: 1,
    score: 0 
  },
   // 更新分数函数
   updateScore: function() {
    let score = 0;
    for (let i = 0; i < 8; i++) {
      for (let j = 0; j < 8; j++) {
        if (box[i][j] == 4 && map[i][j] == 3) {
          score += 10;
        }
      }
    }
    if (score > 100) score = 100; // 确保得分不会超过100

    this.setData({
      score: score
    });

    this.updateScoreDisplay();
  },
  
  updateScoreDisplay: function() {
    this.setData({
      scoreText: `您的得分:${this.data.score}`
    });
  },
  
  /**
   * 生命周期函数--监听页面加载
   */

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值