导航

掷骰子小游戏

Posted on 2020-10-20 14:46  过气书生  阅读(433)  评论(0编辑  收藏  举报
博客班级 https://edu.cnblogs.com/campus/zjcsxy/SE2020
作业要求 https://edu.cnblogs.com/campus/zjcsxy/SE2020/homework/11334
作业目标

1.编写一个小程序,可以全新编写,也可以学习别人的小程序进行修改

2.熟悉git代码管理流程,将源代码上传到到

3.github在博客园班级中写一篇相应的博文

作业源代码 https://github.com/zucc31801111/wxgame.git

学号

姓名

31801111

周云奖

院系 浙大城院计算机系

 

 

 

 

 

 

 

 

 

 

前言

第一次学习做微信小程序,这个小程序的难点在于如何将骰子随机产生的结果的显示以及和预测结果相比较。主要目的还是在于熟悉小程序开发的过程以及相关文件内容的理解,并熟悉git代码的管理流程,代码中已添加注释便于理解。

开发工具:微信开发者工具。

效果演示

 

 

 

全局配置

 app.json

pages:共1个基本页面是骰子游戏页面

window:定义小程序所有页面的顶部背景颜色,文字颜色定义等

小程序根目录下的 sitemap.json文件用于配置小程序及其页面是否允许被微信索引,文件内容为一个 JSON 对象,如果没有 sitemap.json ,则默认为所有页面都允许被索引

{
  "pages": [
    "pages/index/index","pages/game/game"
  ],
  "window": {
    "backgroundTextStyle": "light",
    "navigationBarBackgroundColor": "#fff",
    "navigationBarTitleText": "掷骰子",
    "navigationBarTextStyle": "black"
  },
  "sitemapLocation": "sitemap.json"
}

app.js

主要用于授权后获得微信用户信息

//app.js
App({
  onLaunch: function () {
    // 展示本地存储能力
    wx.clearStorage();
    // 登录
    wx.login({
      success: res => {
        // 发送 res.code 到后台换取 openId, sessionKey, unionId
      }
    })
    // 获取用户信息
    wx.getSetting({
      success: res => {
        if (res.authSetting['scope.userInfo']) {
          // 已经授权,可以直接调用 getUserInfo 获取头像昵称,不会弹框
          wx.getUserInfo({
            success: res => {
              // 可以将 res 发送给后台解码出 unionId
              this.globalData.userInfo = res.userInfo
              // 由于 getUserInfo 是网络请求,可能会在 Page.onLoad 之后才返回
              // 所以此处加入 callback 以防止这种情况
              if (this.userInfoReadyCallback) {
                this.userInfoReadyCallback(res.userInfo)
              }
            }
          })
        }
      }
    })
  },
  globalData: {
    userInfo: null
  }
})

 app.wxss

 全局样式配置文件

/**app.wxss**/

.mt300 {
    margin-top: 300rpx;
}
.mt60 {
    margin-top: 60rpx;
}
.mt200 {
    margin-top: 200rpx;
}
.mr10 {
    margin-right: 10rpx;
}
.mb10 {
    margin-bottom: 10rpx;
}
.w600 {
    width: 600rpx;
}
.w60 {
    width: 60rpx;
}
.h60 {
    height: 60rpx;
}
.w120 {
    width: 120rpx;
}
.h120 {
    height: 120rpx;
}
.text-center {
    text-align: center;
}
.orange-btn {
    background-color: #fba927;
    color: white;
}
.orange-hover {
    background-color: rgba(251, 169, 39, 0.1);
    opacity: 0.7;
}
.container {
    height: 100%;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: space-between;
    padding: 200rpx 0;
    box-sizing: border-box;
}
app.wxss

 

首页部分

页面布局(index.wxml)

显示首页用户头像和信息以及开始按钮和排行榜按钮

<!--index.wxml-->
<view class="container">
  <view class="userinfo">
    <image class="userinfo-avatar" src="{{userInfo.avatarUrl}}" background-size="cover"></image>
    <text class="userinfo-nickname">{{motto}}</text>
    <button wx:if="{{canIUse && !userInfo}}" open-type="getUserInfo" bindgetuserinfo="bindGetUserInfo">授权登录</button>
  </view>
  <view class="mt300">
    <button type="primary" bindtap="goGame" class="w600">
      开始游戏
    </button>
  </view>
</view>

样式文件(index.wxss)

/**index.wxss**/
.userinfo {
    display: flex;
    flex-direction: column;
    align-items: center;
}
.userinfo-avatar {
    width: 128rpx;
    height: 128rpx;
    margin: 20rpx;
    border-radius: 50%;
}
.userinfo-nickname {
    color: #aaa;
}

 运行逻辑(index.js)

//index.js
//获取应用实例
var app = getApp()
Page({
  data: {
    canIUse: wx.canIUse('button.open-type.getUserInfo'),
    motto: '',
    userInfo: null
  },
  //进入游戏
  goGame: function() {
    wx.navigateTo({
      url: '../game/game'
    })
  },
  //处理emoji表情
  killEmoji: function(text) {
    return text.replace(/\uD83C[\uDF00-\uDFFF]|\uD83D[\uDC00-\uDE4F]/g, "");
  },
  //设置用户信息
  setUserInfo: function(userInfo) {
    this.setData({
      userInfo: userInfo,
      motto: '欢迎您,' + userInfo.nickName
    });
    wx.setStorageSync('rankUserInfo', {
      name: userInfo.nickName,
      score: 8000
    });
  },
  //登陆
  onLoad: function() {
    var that = this;
    app.userInfoReadyCallback = res => {
      console.log('回调-获取用户信息成功');
      that.setUserInfo(res);
    };
    if (app.globalData.userInfo) {
      console.log('全局变量-获取用户信息成功');
      that.setUserInfo(app.globalData.userInfo);
    }
  },
  //用户点击授权
  bindGetUserInfo(e) {
    var that = this;
    console.log('主动授权-获取用户信息成功');
    that.setUserInfo(e.detail.userInfo);
  },
  //显示页面
  onShow: function () {
    var that = this;
    if (!that.data.userInfo && app.globalData.userInfo) {
      console.log('全局变量-通过排行榜授权获取用户信息成功');
      that.setUserInfo(app.globalData.userInfo);
    }
  },
})

 

核心部分

 以上内容为小程序的全局配置,以下内容为小程序核心部分主要分为3块内容(内容比较长,采用全部折叠):

 骰子游戏布局(game.wxml)

显示三个骰子的位置,所拥有的分数以及下注金额,码盘,投注对象

<template name="first">
    <view class="dice-box first">
        <span class="dice-point"></span>
    </view>
</template>
<template name="second">
    <view class="dice-box second">
        <span class="dice-point"></span>
        <span class="dice-point self-flex-end"></span>
    </view>
</template>
<template name="third">
    <view class="dice-box third">
        <span class="dice-point"></span>
        <span class="dice-point self-flex-center"></span>
        <span class="dice-point self-flex-end"></span>
    </view>
</template>
<template name="fourth">
    <view class="dice-box fourth">
        <view class="column">
            <span class="dice-point"></span>
            <span class="dice-point"></span>
        </view>
        <view class="column">
            <span class="dice-point"></span>
            <span class="dice-point"></span>
        </view>
    </view>
</template>
<template name="fifth">
    <view class="dice-box fifth">
        <view class="column">
            <span class="dice-point"></span>
            <span class="dice-point"></span>
        </view>
        <view class="column justify-center">
            <span class="dice-point"></span>
        </view>
        <view class="column">
            <span class="dice-point"></span>
            <span class="dice-point"></span>
        </view>
    </view>
</template>
<template name="sixth">
    <view class="dice-box sixth">
        <view class="column">
            <span class="dice-point"></span>
            <span class="dice-point"></span>
            <span class="dice-point"></span>
        </view>
        <view class="column">
            <span class="dice-point"></span>
            <span class="dice-point"></span>
            <span class="dice-point"></span>
        </view>
    </view>
</template>
<view>
    <view class="game-info">
        <div class="name">{{ userInfo.name }}</div>
        <div>
            <span class="money {{moneyClass}}">{{ sigleScore }}</span>
            <div class="score">
                {{ userInfo.score }}
            </div>
        </div>
    </view>
    <view class="dice-body">
        <block wx:for="{{showDiceTemplateArray}}" wx:key="*this">
            <template is="{{item}}" />
        </block>
    </view>
    <view class="column">
                <image mode='aspectFit' data-amount="1" bindtap="setSymbol" class="w120 h120 mb10" src="/images/加.png"></image>
                <image mode='aspectFit' data-amount="2" bindtap="setSymbol" class="w120 h120" src="/images/减.png"></image>
            </view>
    <view class="chip-body">
        <view class="chips">
            <view class="column">
                <image mode='aspectFit' data-amount="50" bindtap="putChip" class="w120 h120 mr10 mb10" src="/images/chip-50.png"></image>
                <image mode='aspectFit' data-amount="100" bindtap="putChip" class="w120 h120 mr10" src="/images/chip-100.png"></image>
            </view>
            <view class="column">
                <image mode='aspectFit' data-amount="200" bindtap="putChip" class="w120 h120 mb10" src="/images/chip-200.png"></image>
                <image mode='aspectFit' data-amount="500" bindtap="putChip" class="w120 h120" src="/images/chip-500.png"></image>
            </view>
        </view>
        <view class="put-chips" bindtouchmove="removeBet" bindtouchend="removeBetEnd">
            <image mode='aspectFit' class="put-chips-img" src="/images/put-chips.png">
            </image>
            <view hidden="{{ showBet }}" class="put-chips-amount {{chipsClass}}">{{ bet > 0? bet:'下注金额' }}</view>
        </view>
    </view>

   

    <view class="game-operate">
        <button data-type="big" bindtap="changeDice">
            <span>大</span>
            <span>1:1</span>
        </button>
        <button data-type="leopard" bindtap="changeDice">
            <span>豹子</span>
            <span>1:24</span>
        </button>
        <button data-type="small" bindtap="changeDice">
            <span>小</span>
            <span>1:1</span>
        </button>
    </view>
</view>
<view hidden="{{ !showBet }}" class="moving-chips-amount"  style="top: {{finger.Y}}px; left: {{finger.X}}px;">{{bet}}</view>
game.wxml

样式文件(game.wxss)

显示骰子,投注,投注对象的位置以及闪烁的效果

.game-info {
    margin: 0 20rpx;
    height: 100rpx;
    display: flex;
    justify-content: space-between;
    align-items: flex-end;
    position: relative;
}
.game-info .score {
    border: 1px solid #eee;
    border-radius: 20%;
    padding: 5rpx 10rpx;
}
.game-info .money {
    color: red;
    position: absolute;
    right: 4px;
    opacity: 0;
    bottom: 0rpx;
}
.game-info .money.change {
    animation: changeMoney ease-in-out 1.5s;
}
/*金钱的动画效果*/
@keyframes changeMoney {
    0% {
        bottom: 0rpx;
        opacity: 0;
    }
    10% {
        bottom: 10rpx;
        opacity: 0.2;
    }
    20% {
        bottom: 20rpx;
        opacity: 0.4;
    }
    30% {
        bottom: 30rpx;
        opacity: 0.6;
    }
    40% {
        bottom: 40rpx;
        opacity: 0.8;
    }
    50% {
        bottom: 50rpx;
        opacity: 1;
    }
    60% {
        bottom: 54rpx;
        opacity: 1;
    }
    75% {
        bottom: 56rpx;
        opacity: 0.6;
    }
    85% {
        bottom: 58rpx;
        opacity: 0.4;
    }
    95% {
        bottom: 60rpx;
        opacity: 0.2;
    }
    100% {
        bottom: 60rpx;
        opacity: 0;
    }
}
.dice-body {
    display: flex;
    flex-wrap: wrap;
    justify-content: space-around;
    margin-top: 20rpx;
}
.dice-box {
    margin: 26rpx;
    padding: 8rpx;
    background-color: #e7e7e7;
    width: 200rpx;
    height: 200rpx;
    box-shadow: inset 0 5px white, inset 0 -5px #bbb, inset 5px 0 #d7d7d7, inset -5px 0 #d7d7d7;
    border-radius: 10%;
}
.dice-point {
    display: block;
    width: 48rpx;
    height: 48rpx;
    border-radius: 50%;
    margin: 8rpx;
    background-color: #333;
    box-shadow: inset 0 6rpx #111, inset 0 -6rpx #555;
}
.self-flex-center {
    align-self: center;
}
.self-flex-end {
    align-self: flex-end;
}
.justify-center {
    justify-content: center !important;
}
.column {
    display: flex;
    flex-direction: column;
    justify-content: space-between;
}
.first {
    display: flex;
    justify-content: center;
    align-items: center;
}
.second {
    display: flex;
    justify-content: space-between;
}
.third {
    display: flex;
}
.fourth,
.sixth,
.fifth {
    display: flex;
    flex-wrap: wrap;
    justify-content: space-between;
}
.chip-body {
    display: flex;
    margin: 10rpx 20rpx 0;
    justify-content: space-between;
}
.chip-body .chips,
.chip-body .put-chips {
    display: flex;
}
.chip-body .put-chips {
    position: relative;
    align-items: center;
    justify-content: center;
}
.chip-body .put-chips .put-chips-img {
    width: 232rpx;
    height: 232rpx;
}
.chip-body .put-chips .put-chips-amount,
.moving-chips-amount {
    position: absolute;
    color: #e0d23e;
    font-size: 32rpx;
    font-weight: bold;
}
.put-chips-amount.blink-smooth {
    animation: 1s blink-smooth 2 alternate;
}
/*闪烁效果*/
@keyframes blink-smooth {
    50% {
        color: transparent
    }
}
.game-operate {
    display: flex;
    margin-top: 40rpx;
}
.game-operate button {
    width: 200rpx;
    height: 200rpx;
    font-size: 24px;
    display: flex;
    justify-content: center;
    flex-direction: column;
    line-height: 60rpx;
}
@media all and (max-height: 480px) {
    .dice-box {
        width: 180rpx;
        height: 180rpx;
        margin: 0.85rem 0;
    }
    .chip-body {
        margin: 40rpx 0.53rem 70rpx;
    }
}
game.wxss

 运行逻辑(game.js)

通过获取随机数搭配通过计算点数和的大小来判断是否与下注的对象相符,判断赌注是否大于0 ,当不大于0时,下注盘会闪烁提示增加赌注。以及结果与预测相同或者不同时,增加或者减小右上角的分数

Page({
    data: {
        userInfo: {},
        bet: 0, // 下注的筹码
        betByCalculate: 0, // 用于计算
        sigleScore: 0, // 本次得分
        showDiceTemplateArray: [], // 用于存储显示哪些骰子模版
        showDiceArray: [0, 1, 2], // 用于存储随机数
        gaming: false, //判断是否在游戏中
        moneyClass: '', // 用于添加金额的动画类
        chipsClass: '', // 用于添加闪烁动画类
        symbol: 0,
        finger: { // 用于移动定位
            Y: 0,
            X: 0
        },
        showBet: false, // 是否显示黑盘中的筹码
        timeArray: []
    },
    getUserInfo: function() {
      return wx.getStorageSync('rankUserInfo');
    },
     //判断加注还是减注
    setSymbol:function(event){
        var that=this;
        var sym= Number(event.currentTarget.dataset.amount)
        this.setData({
            symbol: sym
        });
    },
    putChip: function(event) {
        var that=this;
        if(this.data.symbol==1){
            var chipsSum = Number(this.data.bet) + Number(event.currentTarget.dataset.amount);
            this.setData({
                bet: chipsSum
            });
        }
        else if(this.data.symbol==2){
            var chipsSum = Number(this.data.bet) - Number(event.currentTarget.dataset.amount);
            if(chipsSum<0){
            // 附加闪烁动画
            this.setData({
            chipsClass: "blink-smooth"
          });
             // 清除闪烁动画
          setTimeout(function() {
           this.setData({
            chipsClass: '',
            gaming: false
            });
            }, 2500);
           return
            } 
            else{
                this.setData({
                    bet: chipsSum
                });
            }
        }
        else{
             // 未选择符号 
            // 附加闪烁动画
            this.setData({
                chipsClass: "blink-smooth"
            });
            // 清除闪烁动画
            setTimeout(function() {
                this.setData({
                    chipsClass: '',
                    gaming: false
                });
            }, 2500);
            return
        }
       
    },
    setUserScore: function(score) {
        var that = this;
        // 本次得分赋值, 附加动画
        that.setData({
            moneyClass: 'change',
            sigleScore: score > 0 ? '+' + score : score
        });
        // 改变总分,延迟一点体验比较好
        setTimeout(function() {
            that.setData({
                userInfo: {
                    name: that.data.userInfo.name,
                    score: that.data.userInfo.score + score
                }
            });
          wx.setStorageSync('rankUserInfo', that.data.userInfo);
        }, 660);
        // 清除本次得分动画
        setTimeout(function() {
            that.setData({
                moneyClass: ''
            });
        }, 1500);
    },
    // 判断显示隐藏
    isHidden: function() {
        var templateNameArray = ['first', 'second', 'third', 'fourth', 'fifth', 'sixth'];
        var showDiceArrayTemp = [];
        this.data.showDiceArray.forEach(function(item) {
            showDiceArrayTemp.push(templateNameArray[item]);
        });
        this.setData({
            showDiceTemplateArray: showDiceArrayTemp
        });
    },
    // 返回随机数
    getRandomInt: function(min, max) {
        return Math.floor(Math.random() * (max - min + 1) + min);
    },
    // 游戏开始,骰子变化
    changeDice: function(event) {
        var that = this;
        // 判断是否在游戏
        if (that.data.gaming) {
            return;
        }
        // 设置正在游戏中
        that.setData({
            gaming: true
        });
        // 设置用于该次游戏的赌注
        that.setData({
            betByCalculate: that.data.bet
        });
        // 判断赌注是否大于0 
        if (that.data.betByCalculate <= 0) {
            // 附加闪烁动画
            that.setData({
                chipsClass: "blink-smooth"
            });
            // 清除闪烁动画
            setTimeout(function() {
                that.setData({
                    chipsClass: '',
                    gaming: false
                });
            }, 2500);
            return
        }
        var t1 = setInterval(function() {
            that.data.showDiceArray = [that.getRandomInt(0, 5), that.getRandomInt(0, 5), that.getRandomInt(0, 5)];
            that.isHidden();
        }, 100);
        var t2 = setTimeout(function() {
            clearInterval(t1);
            that.calculateResult(event.currentTarget.dataset.type);
            // 设置没在游戏
            that.setData({
                gaming: false
            });
        }, 2000);
    },
    // 计算猜测结果
    calculateResult: function(userGuess) {
        var rule = {
            'big': function(sum) {
                return sum > 11 && sum < 17;
            },
            'small': function(sum) {
                return sum > 4 && sum < 10;
            }
        }
        var that = this;
        var sum = 3;
        var betByCalculate = that.data.betByCalculate;
        // 豹子
        if (that.data.showDiceArray[0] == that.data.showDiceArray[1] && that.data.showDiceArray[1] == that.data.showDiceArray[2]) {
            if (userGuess == 'leopard') {
                that.setUserScore(24 * betByCalculate);
                return;
            }
        }
        // 选了豹子没中
        if (userGuess == 'leopard') {
            that.setUserScore(-betByCalculate);
            return;
        }
        for (let i = 0; i < that.data.showDiceArray.length; i++) {
            sum += that.data.showDiceArray[i];
        }
        if (rule[userGuess](sum)) {
            that.setUserScore(betByCalculate);
        } else {
            that.setUserScore(-betByCalculate);
        }
    },
    // 移动盘中筹码
    removeBet: function(event) {
        var that = this;
        if (that.data.bet <= 0) {
            return;
        }
        // 隐藏盘中筹码
        if (!that.data.showBet) {
            that.setData({
                showBet: true
            });
        }
        // 只需保存开始、结束时间
        if (that.data.timeArray.length > 1) {
            that.data.timeArray[1] = event.timeStamp;
        } else {
            // 将时间戳push到时间数组
            that.data.timeArray.push(event.timeStamp);
        }
        that.setData({
            finger: {
                Y: event.touches[0].clientY,
                X: event.touches[0].clientX
            }
        });
    },
    // 移动盘中筹码完毕
    removeBetEnd: function() {
        var that = this;
        if (that.data.timeArray.length > 1) {
            var startTime = that.data.timeArray[0];
            var endTime = that.data.timeArray[1];
            if (endTime - startTime > 10) {
                that.setData({
                    showBet: false,
                    bet: 0
                });
            }
            // 清空时间数组
            that.setData({
                timeArray: []
            })
        }
    },
    onLoad: function() {
        var that = this;
        that.setData({
            userInfo: that.getUserInfo()
        });
        that.isHidden();
    }
})
game.js

 

总结与反思

 此小程序目前存在一点明显不足,在于没有减少下注数目,只能够累加。再经过一番摸索之后,独立的实现添加增加减少的图标,能够实现赌注的增加减少。之前并没有接过小程序的开发,参考网络资料的较多,在内部运行的逻辑上还有挺多没理解掌握的,只能说时拼拼凑凑,但是还是有些收获的,知道了如何创建一个小程序以及运行小程序中需要的文件以及相关的代码语法,对于独立创建运行一个小程序还有好多路要走。