Commit d2280fec authored by 董政锦's avatar 董政锦

feat: 游戏开始后的添加倒计时;

parent 455ee499
...@@ -64,7 +64,8 @@ offHorseBoost = onSocketMessage((evt, payload) => { ...@@ -64,7 +64,8 @@ offHorseBoost = onSocketMessage((evt, payload) => {
let hasBoost = false; let hasBoost = false;
data.forEach((item: any) => { data.forEach((item: any) => {
const id = item.userid || item.wechat_id || ""; // WebSocket 数据无 userid/wechat_id,用 avatar 作为稳定标识
const id = item.userid || item.wechat_id || item.avatar || "";
if (!id) return; if (!id) return;
// 尝试多种字段名: score / boost / acceleration / speed / progress // 尝试多种字段名: score / boost / acceleration / speed / progress
const raw = item.score ?? item.boost ?? item.acceleration ?? item.speed ?? item.progress; const raw = item.score ?? item.boost ?? item.acceleration ?? item.speed ?? item.progress;
......
...@@ -46,8 +46,8 @@ const BASE_SPEED_PERCENT_PER_SEC = 100 / BASE_DURATION_SEC; // ≈ 1.111%/s 基 ...@@ -46,8 +46,8 @@ const BASE_SPEED_PERCENT_PER_SEC = 100 / BASE_DURATION_SEC; // ≈ 1.111%/s 基
// ========== 瞬时加速脉冲机制 ========== // ========== 瞬时加速脉冲机制 ==========
// H5 每次摇一摇发送累计积分,PC 端检测 score 增长 → 触发短暂加速脉冲 → 迅速衰减 // H5 每次摇一摇发送累计积分,PC 端检测 score 增长 → 触发短暂加速脉冲 → 迅速衰减
const BOOST_PULSE = 0.8; // 每次操作的加速幅度(+80% 额外速度 const BOOST_PULSE = 1.5; // 每次操作的加速幅度(+150% 额外速度,即 2.5x 基准
const BOOST_DECAY = 0.97; // 每帧衰减系数(60fps 下约 1s 衰减到 16%,约 2s 衰减归零) const BOOST_DECAY = 0.985; // 每帧衰减系数(60fps 下约 1.5s 衰减到 40%,约 3s 衰减归零)
/** 瞬时加速值: { [userid]: currentBoost },每帧衰减 */ /** 瞬时加速值: { [userid]: currentBoost },每帧衰减 */
const transientBoosts = ref<Record<string, number>>({}); const transientBoosts = ref<Record<string, number>>({});
...@@ -61,8 +61,9 @@ const detectScoreChanges = (players: Player[]) => { ...@@ -61,8 +61,9 @@ const detectScoreChanges = (players: Player[]) => {
let hasNewBoost = false; let hasNewBoost = false;
const updated = { ...transientBoosts.value }; const updated = { ...transientBoosts.value };
players.forEach((p) => { players.forEach((p, index) => {
const id = p.userid || p.wechat_id || ""; // WebSocket 数据无 userid/wechat_id,用 avatar 作为稳定标识
const id = p.userid || p.wechat_id || p.avatar || `player-${index}`;
if (!id || id.startsWith("empty-")) return; if (!id || id.startsWith("empty-")) return;
const newScore = Number(p.score ?? 0); const newScore = Number(p.score ?? 0);
const prev = prevScores[id] ?? 0; const prev = prevScores[id] ?? 0;
...@@ -71,6 +72,9 @@ const detectScoreChanges = (players: Player[]) => { ...@@ -71,6 +72,9 @@ const detectScoreChanges = (players: Player[]) => {
// 积分增长 = 玩家又摇了一次 → 触发瞬时加速脉冲 // 积分增长 = 玩家又摇了一次 → 触发瞬时加速脉冲
updated[id] = BOOST_PULSE; updated[id] = BOOST_PULSE;
hasNewBoost = true; hasNewBoost = true;
console.log(
`[Rank1View] 🚀 ${p.nickname} score ${prev}${newScore}, 触发瞬时加速 pulse=${BOOST_PULSE}`,
);
} }
prevScores[id] = newScore; prevScores[id] = newScore;
...@@ -78,10 +82,6 @@ const detectScoreChanges = (players: Player[]) => { ...@@ -78,10 +82,6 @@ const detectScoreChanges = (players: Player[]) => {
if (hasNewBoost) { if (hasNewBoost) {
transientBoosts.value = updated; transientBoosts.value = updated;
console.log(
"[Rank1View] 瞬时加速触发:",
JSON.parse(JSON.stringify(transientBoosts.value)),
);
} }
}; };
...@@ -123,7 +123,8 @@ const updateHorses = (players: Player[]) => { ...@@ -123,7 +123,8 @@ const updateHorses = (players: Player[]) => {
const existingMap = new Map(horses.value.map((h) => [h.id, h])); const existingMap = new Map(horses.value.map((h) => [h.id, h]));
horses.value = validPlayers.map((player, index) => { horses.value = validPlayers.map((player, index) => {
const id = player.userid || player.wechat_id || `horse-${index}`; // WebSocket 数据无 userid/wechat_id,用 avatar 作为稳定标识
const id = player.userid || player.wechat_id || player.avatar || `horse-${index}`;
const existing = existingMap.get(id); const existing = existingMap.get(id);
return { return {
id, id,
...@@ -331,10 +332,13 @@ const startIntro = async () => { ...@@ -331,10 +332,13 @@ const startIntro = async () => {
transientBoosts.value = {}; transientBoosts.value = {};
Object.keys(prevScores).forEach((k) => delete prevScores[k]); Object.keys(prevScores).forEach((k) => delete prevScores[k]);
// Phase 1: 3 秒开场倒计时(背景动画暂停、马匹不显示) // 启动完整倒计时:3s 开场 + 60s 游戏(DesignStage 内部管理两个阶段的 UI)
await designStage.value?.startCountdown(3, 0); const countdownPromise = designStage.value?.startCountdown(3, 60);
// 等待 3-2-1 开场倒计时结束(~3.5s 后安全触发)
await new Promise((r) => setTimeout(r, 3500));
// Phase 2: 倒计时结束 → 游戏正式开始 // Phase 2: 倒计时结束 → 游戏正式开始,背景动画+马匹启动
gameStarted.value = true; gameStarted.value = true;
isGameRunning.value = true; isGameRunning.value = true;
startGameLoop(); startGameLoop();
...@@ -342,20 +346,19 @@ const startIntro = async () => { ...@@ -342,20 +346,19 @@ const startIntro = async () => {
startMockBoost(); startMockBoost();
} }
// Phase 3: 等待游戏结束(最多 60 秒 或 所有马跑完) // 监测提前结束(所有马跑完 → 提前停止倒计时)
const maxMs = 60000; const earlyCheck = setInterval(() => {
const gameStart = Date.now(); const allDone =
await new Promise<void>((resolve) => { horses.value.length > 0 &&
const check = setInterval(() => { horses.value.every((h) => h.xPercent >= 100);
const allDone = horses.value.length > 0 && horses.value.every((h) => h.xPercent >= 100); if (allDone && isGameRunning.value) {
const timeUp = Date.now() - gameStart >= maxMs; designStage.value?.stopCountdown();
if (allDone || timeUp || !isGameRunning.value) { }
clearInterval(check); }, 200);
resolve();
}
}, 200);
});
// 等待 60s 游戏倒计时结束
await countdownPromise;
clearInterval(earlyCheck);
stopGame(); stopGame();
}; };
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment