新建项目
This commit is contained in:
278
pages/game/game.js
Normal file
278
pages/game/game.js
Normal file
@@ -0,0 +1,278 @@
|
||||
const service = require("../../services/game-service");
|
||||
const { formatCountdown, formatTime } = require("../../utils/format");
|
||||
|
||||
Page({
|
||||
data: {
|
||||
code: "",
|
||||
room: null,
|
||||
me: null,
|
||||
readyToRender: false,
|
||||
stageLabel: "",
|
||||
countdown: "00:00",
|
||||
survivors: 0,
|
||||
seekers: 0,
|
||||
captureCode: "",
|
||||
captureTargets: [],
|
||||
selectedTargetId: "",
|
||||
submittedCode: "",
|
||||
skillUsed: false,
|
||||
canManage: false,
|
||||
showDemoCode: false,
|
||||
captureSubmitting: false,
|
||||
errorMessage: "",
|
||||
eventViews: []
|
||||
},
|
||||
|
||||
onLoad(options) {
|
||||
this.setData({ code: options.code || "" });
|
||||
this.tick();
|
||||
},
|
||||
|
||||
onShow() {
|
||||
if (!this.data.code) return;
|
||||
this.startTimer();
|
||||
this.tick();
|
||||
},
|
||||
|
||||
onHide() {
|
||||
this.stopTimer();
|
||||
},
|
||||
|
||||
onUnload() {
|
||||
this.stopTimer();
|
||||
},
|
||||
|
||||
startTimer() {
|
||||
this.stopTimer();
|
||||
this.timer = setInterval(() => this.tick(), 1000);
|
||||
},
|
||||
|
||||
stopTimer() {
|
||||
if (!this.timer) return;
|
||||
clearInterval(this.timer);
|
||||
this.timer = null;
|
||||
},
|
||||
|
||||
tick() {
|
||||
let room = service.getRoom(this.data.code);
|
||||
if (!room) {
|
||||
this.stopTimer();
|
||||
this.setData({ readyToRender: false, errorMessage: "房间不存在或游戏数据已被清理" });
|
||||
return;
|
||||
}
|
||||
if (room.status === "preparing" && Date.now() >= room.phaseEndsAt) {
|
||||
room = service.beginPlaying(room.code);
|
||||
wx.vibrateLong();
|
||||
}
|
||||
if (room.status === "playing") {
|
||||
if (Date.now() >= room.phaseEndsAt) {
|
||||
service.finishGame(room.code, "hiders", null, "timeout");
|
||||
this.goResult();
|
||||
return;
|
||||
}
|
||||
if (room.nextClueAt && Date.now() >= room.nextClueAt) {
|
||||
service.revealClue(room.code);
|
||||
wx.vibrateShort({ type: "medium" });
|
||||
}
|
||||
}
|
||||
if (room.status === "finished") {
|
||||
this.goResult();
|
||||
return;
|
||||
}
|
||||
this.refresh();
|
||||
},
|
||||
|
||||
refresh() {
|
||||
const room = service.getRoom(this.data.code);
|
||||
if (!room) {
|
||||
this.stopTimer();
|
||||
this.setData({ readyToRender: false, errorMessage: "房间不存在或游戏数据已被清理" });
|
||||
return;
|
||||
}
|
||||
const me =
|
||||
room.players.find((player) => player.id === service.USER_ID) ||
|
||||
room.players[0];
|
||||
const seconds = room.status === "paused"
|
||||
? Math.ceil(room.pausedRemainingMs / 1000)
|
||||
: Math.ceil((room.phaseEndsAt - Date.now()) / 1000);
|
||||
const survivors = room.players.filter(
|
||||
(player) => player.role === "hider" && player.status === "hiding"
|
||||
).length;
|
||||
const seekers = room.players.filter(
|
||||
(player) => player.role === "seeker"
|
||||
).length;
|
||||
const captureTargets = room.players.filter(
|
||||
(player) => player.role === "hider" && player.status === "hiding"
|
||||
);
|
||||
const selectedTargetId = captureTargets.some(
|
||||
(player) => player.id === this.data.selectedTargetId
|
||||
)
|
||||
? this.data.selectedTargetId
|
||||
: captureTargets.length ? captureTargets[0].id : "";
|
||||
const currentSkill = me.role === "seeker" ? "radar" : "silent";
|
||||
const captureCode = me.role === "seeker"
|
||||
? service.getCaptureCode(room.code, selectedTargetId)
|
||||
: service.getCaptureCode(room.code, me.id);
|
||||
this.setData({
|
||||
room,
|
||||
errorMessage: "",
|
||||
me,
|
||||
readyToRender: true,
|
||||
stageLabel: room.status === "preparing"
|
||||
? "躲藏准备"
|
||||
: room.status === "paused" ? "游戏已暂停" : "追逃进行中",
|
||||
countdown: formatCountdown(seconds),
|
||||
survivors,
|
||||
seekers,
|
||||
captureTargets,
|
||||
selectedTargetId,
|
||||
captureCode,
|
||||
skillUsed: Boolean(me.skillsUsed && me.skillsUsed[currentSkill] > 0),
|
||||
canManage: room.hostId === service.USER_ID || room.code === "731204",
|
||||
showDemoCode: Boolean(room.runtime && room.runtime.demoAccelerated),
|
||||
eventViews: room.events.slice(0, 6).map((event) => ({
|
||||
...event,
|
||||
time: formatTime(event.createdAt)
|
||||
}))
|
||||
});
|
||||
},
|
||||
|
||||
useSkill() {
|
||||
if (this.data.skillUsed) {
|
||||
wx.showToast({ title: "本局体验技能已使用", icon: "none" });
|
||||
return;
|
||||
}
|
||||
const skill = this.data.me.role === "seeker" ? "radar" : "silent";
|
||||
try {
|
||||
service.useSkill(this.data.code, skill);
|
||||
wx.vibrateShort({ type: "heavy" });
|
||||
this.refresh();
|
||||
} catch (error) {
|
||||
wx.showToast({ title: error.message, icon: "none" });
|
||||
}
|
||||
},
|
||||
|
||||
chooseCaptureTarget(event) {
|
||||
this.setData({
|
||||
selectedTargetId: event.currentTarget.dataset.id,
|
||||
submittedCode: ""
|
||||
});
|
||||
this.refresh();
|
||||
},
|
||||
|
||||
inputCaptureCode(event) {
|
||||
this.setData({
|
||||
submittedCode: event.detail.value.replace(/\D/g, "").slice(0, 4)
|
||||
});
|
||||
},
|
||||
|
||||
fillDemoCode() {
|
||||
this.setData({ submittedCode: this.data.captureCode });
|
||||
},
|
||||
|
||||
submitCapture() {
|
||||
if (this.data.captureSubmitting) return;
|
||||
this.setData({ captureSubmitting: true });
|
||||
try {
|
||||
const room = service.capture(
|
||||
this.data.code,
|
||||
this.data.selectedTargetId,
|
||||
this.data.submittedCode
|
||||
);
|
||||
wx.vibrateLong();
|
||||
this.setData({ submittedCode: "" });
|
||||
if (room.status === "finished") {
|
||||
this.goResult();
|
||||
} else {
|
||||
this.setData({ captureSubmitting: false });
|
||||
wx.showToast({ title: "抓捕成功", icon: "success" });
|
||||
this.refresh();
|
||||
}
|
||||
} catch (error) {
|
||||
this.setData({ captureSubmitting: false });
|
||||
wx.showToast({ title: error.message, icon: "none" });
|
||||
}
|
||||
},
|
||||
|
||||
showSafety() {
|
||||
wx.showActionSheet({
|
||||
itemList: ["我已安全,继续游戏", "联系房主", "退出并前往集合点"],
|
||||
success: (result) => {
|
||||
if (result.tapIndex === 1) {
|
||||
wx.showModal({
|
||||
title: "联系房主",
|
||||
content: "当前原型暂不提供即时通讯,请通过约定的电话或微信联系房主。",
|
||||
showCancel: false
|
||||
});
|
||||
}
|
||||
if (result.tapIndex === 2) {
|
||||
wx.showModal({
|
||||
title: "确认退出?",
|
||||
content: "请先确保自己处于安全位置,并前往约定集合点。",
|
||||
confirmText: "安全退出",
|
||||
confirmColor: "#d9554d",
|
||||
success: (modalResult) => {
|
||||
if (!modalResult.confirm) return;
|
||||
try {
|
||||
const room = service.quitGame(this.data.code);
|
||||
if (room.status === "finished") {
|
||||
this.goResult();
|
||||
} else {
|
||||
this.stopTimer();
|
||||
service.clearCurrentRoom();
|
||||
wx.reLaunch({ url: "/pages/home/home" });
|
||||
}
|
||||
} catch (error) {
|
||||
wx.showToast({ title: error.message, icon: "none" });
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
togglePause() {
|
||||
try {
|
||||
if (this.data.room.status === "paused") {
|
||||
service.resumeGame(this.data.code);
|
||||
} else {
|
||||
service.pauseGame(this.data.code);
|
||||
}
|
||||
this.refresh();
|
||||
} catch (error) {
|
||||
wx.showToast({ title: error.message, icon: "none" });
|
||||
}
|
||||
},
|
||||
|
||||
finishEarly() {
|
||||
wx.showModal({
|
||||
title: "提前结束游戏?",
|
||||
content: "系统将根据当前存活情况立即生成本局战报。",
|
||||
confirmText: "结束游戏",
|
||||
confirmColor: "#d9554d",
|
||||
success: (result) => {
|
||||
if (!result.confirm) return;
|
||||
try {
|
||||
service.finishGame(this.data.code, "", service.USER_ID, "host_ended");
|
||||
this.goResult();
|
||||
} catch (error) {
|
||||
wx.showToast({ title: error.message, icon: "none" });
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
goResult() {
|
||||
this.stopTimer();
|
||||
wx.redirectTo({
|
||||
url: `/pages/result/result?code=${this.data.code}`
|
||||
});
|
||||
},
|
||||
|
||||
backHome() {
|
||||
this.stopTimer();
|
||||
service.clearCurrentRoom();
|
||||
wx.reLaunch({ url: "/pages/home/home" });
|
||||
}
|
||||
});
|
||||
Reference in New Issue
Block a user