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

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