实验六报告

2024年夏季《移动软件开发》实验报告

姓名和学号?
本实验属于哪门课程?中国海洋大学24夏《移动软件开发》
实验名称?实验6:推箱子游戏
博客地址?
Github仓库地址?

一、实验目标

1、综合所学知识创建完整的推箱子游戏;2、能够在开发过程中熟练掌握真机预览、调试等操作。

二、实验步骤

1.视图设计

1)导航栏设计

app.json代码如下:

  "window": {
      "navigationBarBackgroundColor": "#E64340",
      "navigationBarTitleText": "推箱子游戏"
  },
2)页面设计
公共样式设计

app.wxss代码如下:

/* 引入 weui 组件 */
@import './miniprogram_npm/weui-miniprogram/weui-wxss/dist/style/weui.wxss';

page {
  --footer-height: 10vh;
  --button-size: 16vw;
  --button-color: #353535;
  --button-icon-size: 6vw;
}

page {
  background: #f6f6f6;
  display: flex;
  flex-direction: column;
  justify-content: flex-start;
}

.container {
  display: flex;
  flex-direction: column;
  align-items: center;
  box-sizing: border-box;
  min-height: 100vh;
  overflow-x: hidden;
}

button {
  background: initial;
}

button:focus {
  outline: 0;
}

button::after {
  border: none;
}

.form-group {
  width: calc(100% - 40px);
  margin: 10px 20px;
  border-radius: 10px;
  background: white;
}

.form-group_label {
  align-self: flex-start;
  margin-left: 20px;
  color: #8D8D8D;
  font-size: 15px;
}

.form-group_label:not(:first-child) {
  margin-top: 20px;
}

.form-cell {
  padding: 20px 15px;
}

.form-cell:not(:last-child) {
  border-bottom: rgba(0, 0, 0, 0.05) solid 1px;
}

.form-cell.inline {
  display: flex;
  justify-content: flex-start;
  align-items: center;
}
首页设计

pages/index/index.wxml代码如下:

<!--index.wxml-->
<view class="container">
    <!--标题-->
    <view class="title">游戏选关</view>
    <!--关卡列表-->
    <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>

pages/index/index.wxss代码如下:

.container {
    display: flex;
    flex-direction: column;
    height: 100%;
  }
  
  .header {
    display: flex;
    justify-content: space-between;
    align-items: center;
    padding: 20rpx;
    background-color: #fff;
  }
  
  .back-icon, .more-icon, .scan-icon {
    width: 40rpx;
    height: 40rpx;
  }
  
  .title {
    font-size: 36rpx;
    font-weight: bold;
  }
  
  .more-options {
    display: flex;
    align-items: center;
  }
  
  .user-info {
    display: flex;
    align-items: center;
    padding: 20rpx;
    background-color: #fff;
  }
  
  .user-icon {
    width: 80rpx;
    height: 80rpx;
    margin-right: 20rpx;
  }
  
  .user-name {
    display: flex;
    flex-direction: column;
  }
  
  .user-name text {
    font-size: 32rpx;
    margin-bottom: 10rpx;
  }
  
  .options {
    display: flex;
    flex-wrap: wrap;
    border-top: 1px solid #ebebeb;
    border-bottom: 1px solid #ebebeb;
  }
  
  .option {
    flex: 1;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    padding: 20rpx;
    border-right: 1px solid #ebebeb;
  }
  
  .option-icon {
    width: 60rpx;
    height: 60rpx;
    margin-bottom: 10rpx;
  }
  
  .section {
    display: flex;
    flex-direction: column;
    padding: 20rpx;
    border-bottom: 1px solid #ebebeb;
  }
  
  .section-title {
    display: flex;
    justify-content: space-between;
    align-items: center;
  }
  
  .arrow-right {
    width: 20rpx;
    height: 20rpx;
  }
  
  .section-description {
    margin-top: 10rpx;
    font-size: 28rpx;
    color: #666;
  }
  page {
    background-color: #f8f8f8;
  }
  
  .login-container {
    height: 400rpx;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    position: relative;
    overflow: hidden;
  }
  
  /* 图标的样式 */
  .contact-filled {
    width: 150rpx;
    margin-bottom: 16rpx;
  }
  
  /* 登录按钮的样式 */
  .btn-login {
    width: 90%;
    border-radius: 100px;
    margin: 15px 0;
    background-color: #3F3F3F;
    color: #f8f8f8;
  }
  
  /* 按钮下方提示消息的样式 */
  .tips-text {
    font-size: 12px;
    color: gray;
  }
游戏页面设计

pages/game/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>

pages/game/game.wxss代码如下:

/* pages/game/game.wxss */
/*游戏画布样式*/
canvas{
    border:lrpx 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;
}

2.逻辑实现

1)公共逻辑

utils/data.js代码如下:

//关卡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]
}
2)首页逻辑

pages/index/index.js代码如下:

// 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
          }
      )
  },
3)游戏页逻辑

pages/game/game.js代码如下:

// 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 = 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()
    },
    /**
     * 生命周期函数--监听页面加载
     */
    onLoad(options) {
        //获取关卡
        let level = options.level
        //更新页面关卡标题
        this.setData(
            {
                level:parseInt(level) + 1
            }
        )
        //创建画布上下文
        this.ctx = wx.createCanvasContext("myCanvas")
        //初始化地图数据
        this.initMap(level)
        //绘制画布内容
        this.drawCanvas()
    },

    //上
    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()
    }
})

三、程序运行结果

image-20240903211502848image-20240903211525015image-20240903211606884image-20240903211651387

四、问题总结与体会

在本次实验中,面对的主要挑战在于理解和实现游戏的逻辑,特别是玩家角色与环境的交互,如移动和推箱动作的检测与执行。比如,在处理玩家移动时,需要确保地图上的每个位置都可以正确响应玩家的动作,同时还要考虑到箱子的存在可能会阻碍移动等等。本次实验加深了我对前端开发流程的认识,在响应式设计和代码调试方面有了更多的实践经验。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值