You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
254 lines
7.4 KiB
254 lines
7.4 KiB
5 years ago
|
"use strict";
|
||
|
|
||
|
require('../../lib/regenerator-runtime');
|
||
|
|
||
|
const regeneratorRuntime = global.regeneratorRuntime;
|
||
|
|
||
|
// 引入 co 和 promisify 帮助我们进行异步处理
|
||
|
const co = require('../../lib/co');
|
||
|
const promisify = require('../../lib/promisify');
|
||
|
|
||
|
// 引入 Wafer 客户端 SDK 支持会话
|
||
|
const wafer = require('../../vendors/wafer-client-sdk/index');
|
||
|
|
||
|
// 简单的小程序 WebSocket 信道封装
|
||
|
const Tunnel = require('../../lib/tunnel');
|
||
|
|
||
|
// 登录接口转成返回 Promise 形式
|
||
|
const login = promisify(wafer.login);
|
||
|
|
||
|
// 获得小程序实例
|
||
|
const app = getApp();
|
||
|
|
||
|
// 用于记录实验成功
|
||
|
const lab = require('../../lib/lab');
|
||
|
|
||
|
// 设置会话登录地址
|
||
|
wafer.setLoginUrl(`https://${app.config.host}/login`);
|
||
|
|
||
|
// 文案
|
||
|
const WIN_TEXTS = ['很棒', '秒杀', '赢了', 'Winner', '胜利', '不要大意', '无敌啊'];
|
||
|
const LOSE_TEXTS = ['失误', '卧槽', '不可能', 'Loser', '行不行啊', '加油', '大侠再来'];
|
||
|
const EQ_TEXTS = ['平局', '平分秋色', '对方学你', '照镜子', '半斤八两', '换一个', '一样的'];
|
||
|
const pickText = texts => texts[Math.floor(texts.length * Math.random())];
|
||
|
|
||
|
// 定义页面
|
||
|
Page({
|
||
|
data: {
|
||
|
// 是否已经和服务器连接
|
||
|
connected: false,
|
||
|
|
||
|
// 游戏是否进行中
|
||
|
playing: false,
|
||
|
|
||
|
// 当前需要展示的游戏信息
|
||
|
gameInfo: "",
|
||
|
|
||
|
// 开始游戏按钮文本
|
||
|
startButtonText: "开始",
|
||
|
|
||
|
//「我」的信息,包括昵称、头像、分数、选择
|
||
|
myName: "",
|
||
|
myAvatar: null,
|
||
|
myScore: 0,
|
||
|
myStreak: 0,
|
||
|
myChoice: Math.floor(Math.random() * 10000) % 3 + 1,
|
||
|
|
||
|
//「你」的信息
|
||
|
youHere: false,
|
||
|
yourName: "",
|
||
|
yourAvatar: null,
|
||
|
yourScore: 0,
|
||
|
yourStreak: 0,
|
||
|
yourChoice: 1,
|
||
|
yourMove: 0,
|
||
|
|
||
|
// 取得胜利的是谁
|
||
|
win: null
|
||
|
},
|
||
|
|
||
|
// 页面显示后,开始连接
|
||
|
onShow: function() {
|
||
|
this.begin();
|
||
|
},
|
||
|
|
||
|
// 进行登录和链接,完成后开始启动游戏服务
|
||
|
begin: co.wrap(function *() {
|
||
|
try {
|
||
|
this.setData({ gameInfo: "正在登陆" });
|
||
|
yield login();
|
||
|
|
||
|
this.setData({ gameInfo: "正在连接"});
|
||
|
yield this.connect();
|
||
|
} catch (error) {
|
||
|
console.error('error on login or connect: ', error);
|
||
|
}
|
||
|
this.serve();
|
||
|
}),
|
||
|
|
||
|
// 链接到服务器后进行身份识别
|
||
|
connect: co.wrap(function *() {
|
||
|
|
||
|
const tunnel = this.tunnel = new Tunnel();
|
||
|
try {
|
||
|
yield tunnel.connect(`wss://${app.config.host}/game`, wafer.buildSessionHeader());
|
||
|
} catch (connectError) {
|
||
|
console.error({ connectError });
|
||
|
this.setData({ gameInfo: "连接错误" });
|
||
|
throw connectError;
|
||
|
}
|
||
|
tunnel.on('close', () => {
|
||
|
this.setData({
|
||
|
connected: false,
|
||
|
gameInfo: "连接已中断"
|
||
|
});
|
||
|
});
|
||
|
this.setData({
|
||
|
gameInfo: "准备",
|
||
|
connected: true,
|
||
|
gameState: 'connected'
|
||
|
});
|
||
|
return new Promise((resolve, reject) => {
|
||
|
// 10 秒后超时
|
||
|
const timeout = setTimeout(() => reject, 10000);
|
||
|
tunnel.on('id', ({ uname, uid, uavatar }) => {
|
||
|
this.uid = uid;
|
||
|
this.setData({
|
||
|
myName: uname,
|
||
|
myAvatar: uavatar
|
||
|
});
|
||
|
resolve(tunnel);
|
||
|
clearTimeout(timeout);
|
||
|
});
|
||
|
});
|
||
|
}),
|
||
|
|
||
|
// 开始进行游戏服务
|
||
|
serve: co.wrap(function *() {
|
||
|
const tunnel = this.tunnel;
|
||
|
|
||
|
// 游戏开始,初始化对方信息,启动计时器
|
||
|
tunnel.on('start', packet => {
|
||
|
const you = packet.players.filter(user => user.uid !== this.uid).pop();
|
||
|
|
||
|
this.setData({
|
||
|
playing: false,
|
||
|
done: false,
|
||
|
finding: true,
|
||
|
gameInfo: '正在寻找玩伴...'
|
||
|
});
|
||
|
setTimeout(() => {
|
||
|
this.setData({
|
||
|
youHere: true,
|
||
|
yourName: you.uname,
|
||
|
yourAvatar: you.uavatar,
|
||
|
finding: false,
|
||
|
playing: true,
|
||
|
gameInfo: "准备"
|
||
|
});
|
||
|
}, 10);
|
||
|
|
||
|
let gameTime = packet.gameTime;
|
||
|
clearInterval(this.countdownId);
|
||
|
this.countdownId = setInterval(() => {
|
||
|
if (gameTime > 0) {
|
||
|
this.setData({ gameInfo: --gameTime });
|
||
|
} else {
|
||
|
clearInterval(this.countdownId);
|
||
|
}
|
||
|
}, 1000);
|
||
|
|
||
|
this.tunnel.emit('choice', { choice: this.data.myChoice });
|
||
|
});
|
||
|
|
||
|
// 对方有动静的时候,触发提醒
|
||
|
let movementTimer = 0;
|
||
|
const movementTimeout = 300;
|
||
|
tunnel.on('movement', packet => {
|
||
|
const lastMove = this.lastMove;
|
||
|
|
||
|
this.setData({ yourMove: lastMove == 1 ? 2 : 1 });
|
||
|
|
||
|
clearTimeout(movementTimer);
|
||
|
movementTimer = setTimeout(() => {
|
||
|
this.lastMove = this.data.yourMove;
|
||
|
this.setData({ yourMove: 0 });
|
||
|
}, 300);
|
||
|
});
|
||
|
|
||
|
// 服务器通知结果
|
||
|
tunnel.on('result', packet => {
|
||
|
|
||
|
// 清除计时器
|
||
|
clearInterval(this.countdownId);
|
||
|
|
||
|
// 双方结果
|
||
|
const myResult = packet.result.find(x => x.uid == this.uid);
|
||
|
const yourResult = packet.result.find(x => x.uid != this.uid);
|
||
|
|
||
|
// 本局结果
|
||
|
let gameInfo, win = 'nobody';
|
||
|
|
||
|
if (myResult.roundScore == 0 && yourResult.roundScore == 0) {
|
||
|
gameInfo = pickText(EQ_TEXTS);
|
||
|
}
|
||
|
else if (myResult.roundScore > 0) {
|
||
|
gameInfo = pickText(WIN_TEXTS);
|
||
|
win = 'me';
|
||
|
}
|
||
|
else {
|
||
|
gameInfo = pickText(LOSE_TEXTS);
|
||
|
win = 'you'
|
||
|
}
|
||
|
|
||
|
// 更新到视图
|
||
|
this.setData({
|
||
|
gameInfo,
|
||
|
myScore: myResult.totalScore,
|
||
|
myStreak: myResult.winStreak,
|
||
|
yourChoice: yourResult.choice,
|
||
|
yourScore: yourResult.totalScore,
|
||
|
yourStreak: yourResult.winStreak,
|
||
|
gameState: 'finish',
|
||
|
win,
|
||
|
startButtonText: win == 'you' ? "不服" : "再来",
|
||
|
done: true
|
||
|
});
|
||
|
|
||
|
lab.finish('game');
|
||
|
setTimeout(() => this.setData({ playing: false }), 1000);
|
||
|
});
|
||
|
}),
|
||
|
|
||
|
requestComputer() {
|
||
|
if (this.tunnel) {
|
||
|
this.tunnel.emit('requestComputer');
|
||
|
}
|
||
|
},
|
||
|
|
||
|
// 点击开始游戏按钮,发送加入游戏请求
|
||
|
startGame: co.wrap(function *() {
|
||
|
if (this.data.playing) return;
|
||
|
if (!this.data.connected) return;
|
||
|
|
||
|
this.setData({
|
||
|
playing: false,
|
||
|
done: false,
|
||
|
finding: true,
|
||
|
gameInfo: '正在寻找玩伴...'
|
||
|
});
|
||
|
this.tunnel.emit('join');
|
||
|
}),
|
||
|
|
||
|
// 点击手势,更新选择是石头、剪刀还是布
|
||
|
switchChoice(e) {
|
||
|
if (!this.data.playing) return;
|
||
|
let myChoice = this.data.myChoice + 1;
|
||
|
if (myChoice == 4) {
|
||
|
myChoice = 1;
|
||
|
}
|
||
|
this.setData({ myChoice });
|
||
|
this.tunnel.emit('choice', { choice: myChoice });
|
||
|
}
|
||
|
});
|