Commit 82ea5e29 authored by 董政锦's avatar 董政锦

feat: 注释 PC game2-5的本地模式模拟数据;

parent d82cb786
......@@ -47,11 +47,7 @@ const mockPlayers = [
{ userid: 'local-10', nickname: '踏雪无痕', avatar: 'https://api.dicebear.com/9.x/fun-emoji/svg?seed=Tiger', score: 18 },
];
const loadingPlayers = ref<any[]>(
$is_local_mode()
? mockPlayers
: Array.from({ length: PLAYER_LIMIT }, emptyLoadingPlayer)
)
const loadingPlayers = ref<any[]>(Array.from({ length: PLAYER_LIMIT }, emptyLoadingPlayer))
const playerCount = ref(0)
const rankPlayers = ref<Player[]>(Array.from({ length: RANK_LIMIT }, (_, index) => emptyRankPlayer(index)))
const rank1Ref = ref<InstanceType<typeof Rank1> | null>(null)
......@@ -65,20 +61,27 @@ const confirmRefresh = (event: BeforeUnloadEvent) => {
const renderPlayers = (data: any) => {
const players = Array.isArray(data?.list) ? data.list : []
console.log('[game2] renderPlayers 收到数据:', JSON.stringify(data), '玩家数:', players.length)
playerCount.value = Number(data?.count ?? players.length)
loadingPlayers.value = Array.from(
{ length: PLAYER_LIMIT },
(_, index) => players[index] ?? emptyLoadingPlayer(),
)
console.log('[game2] renderPlayers 更新后 loadingPlayers:', loadingPlayers.value.slice(0, 3).map(p => ({ nickname: p.nickname, userid: p.userid })))
}
const updateRankPlayers = (data: any) => {
if (!Array.isArray(data)) return
console.log('[game2] updateRankPlayers 收到数据:', JSON.stringify(data))
if (!Array.isArray(data)) {
console.warn('[game2] updateRankPlayers: 数据不是数组')
return
}
rankPlayers.value = Array.from(
{ length: RANK_LIMIT },
(_, index) => data[index] ?? emptyRankPlayer(index),
)
console.log('[game2] updateRankPlayers 更新后 rankPlayers:', JSON.stringify(rankPlayers.value.map(p => ({ nickname: p.nickname, userid: p.userid }))))
}
const playerToRankPlayer = (player: any, index: number): Player => ({
......@@ -152,11 +155,9 @@ const { startGame, createRoom, backRoom, closeRoom } = useAdminGameSocket({
break
case 2:
seedRankPlayersFromLoading()
debugger
screen.value = 'rank1'
break
case 3:
debugger
screen.value = 'rank2'
break
}
......@@ -174,10 +175,11 @@ const { startGame, createRoom, backRoom, closeRoom } = useAdminGameSocket({
})
const startGameWithMusic = () => {
if ($is_local_mode()) {
gotoRank1WithIntro()
return
}
// 本地模拟已关闭,如需开启请取消以下注释
// if ($is_local_mode()) {
// gotoRank1WithIntro()
// return
// }
if (playerCount.value == 0) {
$toast('房间中没有玩家');
return;
......
......@@ -161,7 +161,9 @@ const createRandomLanesByRank = () => {
let lanesByRank = createRandomLanesByRank();
const syncRacers = (rankList: Player[]) => {
console.log('[game2 Rank1View] syncRacers 收到 rankList:', rankList.length, '条', rankList.slice(0, 3).map(p => ({ nickname: p.nickname, userid: p.userid, wechat_id: p.wechat_id })));
const topPlayers = rankList.filter(isRealPlayer).slice(0, HORSE_COUNT);
console.log('[game2 Rank1View] syncRacers 过滤后 topPlayers:', topPlayers.length, '条', topPlayers.map(p => p.nickname));
const rankedEntries = topPlayers.map((player, index) => ({
key: playerKey(player, index),
player,
......@@ -202,6 +204,7 @@ const syncRacers = (rankList: Player[]) => {
racers.value = [...retained, ...newcomers]
.sort((a, b) => a.lane - b.lane);
rankedPlayerKeys.value = topKeys;
console.log('[game2 Rank1View] syncRacers 最终 racers:', racers.value.length, '匹马');
};
const updateRacePositions = (tickScale = 1) => {
......@@ -327,46 +330,47 @@ onMounted(() => {
preloadHorseSprites();
raceAnimationFrame = window.requestAnimationFrame(animateRace);
if ($is_local_mode()) {
const mockAvatars = [
'https://api.dicebear.com/9.x/fun-emoji/svg?seed=Felix',
'https://api.dicebear.com/9.x/fun-emoji/svg?seed=Aneka',
'https://api.dicebear.com/9.x/fun-emoji/svg?seed=Salem',
'https://api.dicebear.com/9.x/fun-emoji/svg?seed=Midnight',
'https://api.dicebear.com/9.x/fun-emoji/svg?seed=Lucky',
'https://api.dicebear.com/9.x/fun-emoji/svg?seed=Bandit',
];
const mockData: Player[] = [
{ userid: 'local-1', nickname: '疾风骑士', avatar: mockAvatars[0], score: 45 },
{ userid: 'local-2', nickname: '闪电侠', avatar: mockAvatars[1], score: 38 },
{ userid: 'local-3', nickname: '追风者', avatar: mockAvatars[2], score: 30 },
{ userid: 'local-4', nickname: '千里马', avatar: mockAvatars[3], score: 22 },
{ userid: 'local-5', nickname: '飞毛腿', avatar: mockAvatars[4], score: 15 },
{ userid: 'local-6', nickname: '烈焰驹', avatar: mockAvatars[5], score: 52 },
];
syncRacers(mockData);
const growthRates: Record<string, number> = {};
mockData.forEach((p, i) => {
growthRates[p.userid!] = 0.4 + (i / (mockData.length - 1)) * 1.4;
});
let simInterval: ReturnType<typeof setInterval> | undefined;
watch(raceStarted, (running) => {
if (simInterval) { clearInterval(simInterval); simInterval = undefined; }
if (running) {
simInterval = setInterval(() => {
if (!raceStarted.value) { clearInterval(simInterval); simInterval = undefined; return; }
const updatedPlayers = racers.value.map(r => ({
...r.player,
score: Number(r.player.score || 0) + Math.floor(Math.random() * 10 + 5),
}));
updatedPlayers.sort((a, b) => Number(b.score) - Number(a.score));
syncRacers(updatedPlayers);
}, 1500);
}
}, { immediate: true });
}
// 本地模拟已关闭,如需开启请取消以下注释
// if ($is_local_mode()) {
// const mockAvatars = [
// 'https://api.dicebear.com/9.x/fun-emoji/svg?seed=Felix',
// 'https://api.dicebear.com/9.x/fun-emoji/svg?seed=Aneka',
// 'https://api.dicebear.com/9.x/fun-emoji/svg?seed=Salem',
// 'https://api.dicebear.com/9.x/fun-emoji/svg?seed=Midnight',
// 'https://api.dicebear.com/9.x/fun-emoji/svg?seed=Lucky',
// 'https://api.dicebear.com/9.x/fun-emoji/svg?seed=Bandit',
// ];
// const mockData: Player[] = [
// { userid: 'local-1', nickname: '疾风骑士', avatar: mockAvatars[0], score: 45 },
// { userid: 'local-2', nickname: '闪电侠', avatar: mockAvatars[1], score: 38 },
// { userid: 'local-3', nickname: '追风者', avatar: mockAvatars[2], score: 30 },
// { userid: 'local-4', nickname: '千里马', avatar: mockAvatars[3], score: 22 },
// { userid: 'local-5', nickname: '飞毛腿', avatar: mockAvatars[4], score: 15 },
// { userid: 'local-6', nickname: '烈焰驹', avatar: mockAvatars[5], score: 52 },
// ];
// syncRacers(mockData);
//
// const growthRates: Record<string, number> = {};
// mockData.forEach((p, i) => {
// growthRates[p.userid!] = 0.4 + (i / (mockData.length - 1)) * 1.4;
// });
//
// let simInterval: ReturnType<typeof setInterval> | undefined;
// watch(raceStarted, (running) => {
// if (simInterval) { clearInterval(simInterval); simInterval = undefined; }
// if (running) {
// simInterval = setInterval(() => {
// if (!raceStarted.value) { clearInterval(simInterval); simInterval = undefined; return; }
// const updatedPlayers = racers.value.map(r => ({
// ...r.player,
// score: Number(r.player.score || 0) + Math.floor(Math.random() * 10 + 5),
// }));
// updatedPlayers.sort((a, b) => Number(b.score) - Number(a.score));
// syncRacers(updatedPlayers);
// }, 1500);
// }
// }, { immediate: true });
// }
});
onBeforeUnmount(() => {
......
......@@ -231,11 +231,11 @@ const { startGame, createRoom, backRoom, closeRoom } = useAdminGameSocket({
})
const startGameWithMusic = () => {
// 本地调试模式:跳过 WebSocket,直接进入赛马画面
if ($is_local_mode()) {
gotoRank1WithIntro()
return
}
// 本地调试模式已关闭,如需开启请取消以下注释
// if ($is_local_mode()) {
// gotoRank1WithIntro()
// return
// }
if (playerCount.value == 0) {
$toast('房间中没有玩家');
return;
......
......@@ -422,57 +422,54 @@ const renderAvatar = (item: any | null) => {
onMounted(() => {
preloadHorseFrames();
if ($is_local_mode()) {
// 本地模式:预填10个模拟玩家数据,由 startIntro 流程驱动赛马
const mockAvatars = [
'https://api.dicebear.com/9.x/fun-emoji/svg?seed=Felix',
'https://api.dicebear.com/9.x/fun-emoji/svg?seed=Aneka',
'https://api.dicebear.com/9.x/fun-emoji/svg?seed=Salem',
'https://api.dicebear.com/9.x/fun-emoji/svg?seed=Midnight',
'https://api.dicebear.com/9.x/fun-emoji/svg?seed=Lucky',
'https://api.dicebear.com/9.x/fun-emoji/svg?seed=Bandit',
'https://api.dicebear.com/9.x/fun-emoji/svg?seed=Misty',
'https://api.dicebear.com/9.x/fun-emoji/svg?seed=Pepper',
'https://api.dicebear.com/9.x/fun-emoji/svg?seed=Oreo',
'https://api.dicebear.com/9.x/fun-emoji/svg?seed=Tiger',
];
list.value = [
{ userid: 'local-1', nickname: '疾风骑士', avatar: mockAvatars[0], score: 45 },
{ userid: 'local-2', nickname: '闪电侠', avatar: mockAvatars[1], score: 38 },
{ userid: 'local-3', nickname: '追风者', avatar: mockAvatars[2], score: 30 },
{ userid: 'local-4', nickname: '千里马', avatar: mockAvatars[3], score: 22 },
{ userid: 'local-5', nickname: '飞毛腿', avatar: mockAvatars[4], score: 15 },
{ userid: 'local-6', nickname: '烈焰驹', avatar: mockAvatars[5], score: 52 },
{ userid: 'local-7', nickname: '暴风战士', avatar: mockAvatars[6], score: 41 },
{ userid: 'local-8', nickname: '神行者', avatar: mockAvatars[7], score: 35 },
{ userid: 'local-9', nickname: '银鞍客', avatar: mockAvatars[8], score: 28 },
{ userid: 'local-10', nickname: '踏雪无痕', avatar: mockAvatars[9], score: 18 },
];
// 每匹马不同的基础增速:领先者(高分)增速更高,自然拉开差距
const growthRates: Record<string, number> = {};
list.value.forEach((p, i) => {
// 高分马增速 1.4~1.8x,低分马 0.6~1.0x,制造持久速度差异
growthRates[p.userid!] = 0.4 + (i / (list.value.length - 1)) * 1.4;
});
// 跟随 isGameRunning 自动管理模拟分数组件
let simInterval: ReturnType<typeof setInterval> | undefined;
watch(isGameRunning, (running) => {
if (simInterval) { clearInterval(simInterval); simInterval = undefined; }
if (running) {
simInterval = setInterval(() => {
if (!isGameRunning.value) { clearInterval(simInterval); simInterval = undefined; return; }
for (const p of list.value) {
if (typeof p.score === 'number' && p.score < 120 && p.userid) {
const rate = growthRates[p.userid] || 1.0;
const growth = Math.max(1, Math.floor((Math.random() * 3 + 1) * rate));
p.score += growth;
}
}
detectScoreChanges(list.value);
}, 1500);
}
}, { immediate: true });
}
// 本地模拟已关闭,如需开启请取消以下注释
// if ($is_local_mode()) {
// const mockAvatars = [
// 'https://api.dicebear.com/9.x/fun-emoji/svg?seed=Felix',
// 'https://api.dicebear.com/9.x/fun-emoji/svg?seed=Aneka',
// 'https://api.dicebear.com/9.x/fun-emoji/svg?seed=Salem',
// 'https://api.dicebear.com/9.x/fun-emoji/svg?seed=Midnight',
// 'https://api.dicebear.com/9.x/fun-emoji/svg?seed=Lucky',
// 'https://api.dicebear.com/9.x/fun-emoji/svg?seed=Bandit',
// 'https://api.dicebear.com/9.x/fun-emoji/svg?seed=Misty',
// 'https://api.dicebear.com/9.x/fun-emoji/svg?seed=Pepper',
// 'https://api.dicebear.com/9.x/fun-emoji/svg?seed=Oreo',
// 'https://api.dicebear.com/9.x/fun-emoji/svg?seed=Tiger',
// ];
// list.value = [
// { userid: 'local-1', nickname: '疾风骑士', avatar: mockAvatars[0], score: 45 },
// { userid: 'local-2', nickname: '闪电侠', avatar: mockAvatars[1], score: 38 },
// { userid: 'local-3', nickname: '追风者', avatar: mockAvatars[2], score: 30 },
// { userid: 'local-4', nickname: '千里马', avatar: mockAvatars[3], score: 22 },
// { userid: 'local-5', nickname: '飞毛腿', avatar: mockAvatars[4], score: 15 },
// { userid: 'local-6', nickname: '烈焰驹', avatar: mockAvatars[5], score: 52 },
// { userid: 'local-7', nickname: '暴风战士', avatar: mockAvatars[6], score: 41 },
// { userid: 'local-8', nickname: '神行者', avatar: mockAvatars[7], score: 35 },
// { userid: 'local-9', nickname: '银鞍客', avatar: mockAvatars[8], score: 28 },
// { userid: 'local-10', nickname: '踏雪无痕', avatar: mockAvatars[9], score: 18 },
// ];
// const growthRates: Record<string, number> = {};
// list.value.forEach((p, i) => {
// growthRates[p.userid!] = 0.4 + (i / (list.value.length - 1)) * 1.4;
// });
// let simInterval: ReturnType<typeof setInterval> | undefined;
// watch(isGameRunning, (running) => {
// if (simInterval) { clearInterval(simInterval); simInterval = undefined; }
// if (running) {
// simInterval = setInterval(() => {
// if (!isGameRunning.value) { clearInterval(simInterval); simInterval = undefined; return; }
// for (const p of list.value) {
// if (typeof p.score === 'number' && p.score < 120 && p.userid) {
// const rate = growthRates[p.userid] || 1.0;
// const growth = Math.max(1, Math.floor((Math.random() * 3 + 1) * rate));
// p.score += growth;
// }
// }
// detectScoreChanges(list.value);
// }, 1500);
// }
// }, { immediate: true });
// }
});
onUnmounted(() => {
......
......@@ -197,11 +197,12 @@ const startGameWithMusic = () => {
console.log('[Game4] startGameWithMusic called, local mode:', $is_local_mode(), 'playerCount:', playerCount.value)
// 确保背景音乐播放(参考 game2 的 watch 模式,但直接在点击时调用更可靠)
playGame4Music()
if ($is_local_mode()) {
console.log('[Game4] 本地模式,直接进入赛马画面')
gotoRank1WithIntro()
return
}
// 本地模拟已关闭,如需开启请取消以下注释
// if ($is_local_mode()) {
// console.log('[Game4] 本地模式,直接进入赛马画面')
// gotoRank1WithIntro()
// return
// }
if (playerCount.value == 0) {
$toast('房间中没有玩家');
return;
......@@ -213,11 +214,11 @@ const startGameWithMusic = () => {
const nextRound = () => {
// 立刻停止喝彩音乐并移除指针事件监听,防止点击按钮时重新触发 playApplauseMusic
stopApplauseMusic()
if ($is_local_mode()) {
// 本地模式:回到 loading 页,用户点击"开始挑战"后再进入赛马(对齐 game3)
gotoLoading(true)
return
}
// 本地模拟已关闭,如需开启请取消以下注释
// if ($is_local_mode()) {
// gotoLoading(true)
// return
// }
gotoLoading(true)
// 等待 Rank1View 卸载完成后再确保 BGM 播放(对齐 game3 的 watch 模式)
// 用 nextTick 确保在组件卸载、watch 触发的 BGM 之后再次保证
......@@ -233,11 +234,12 @@ const nextRoundWithMusic = () => {
const backHandler = async() => {
// 立刻停止喝彩音乐并移除指针事件监听,防止点击按钮时重新触发 playApplauseMusic
stopApplauseMusic()
if ($is_local_mode()) {
stopAllMusic()
router.replace('/main')
return
}
// 本地模拟已关闭,如需开启请取消以下注释
// if ($is_local_mode()) {
// stopAllMusic()
// router.replace('/main')
// return
// }
const ok = await $confirm({
title: '提示',
message: '是否关闭当前房间回到首页',
......
......@@ -409,9 +409,10 @@ const stopGame = () => {
};
const startIntro = async () => {
if ($is_local_mode()) {
mockHorses();
}
// 本地模拟已关闭,如需开启请取消以下注释
// if ($is_local_mode()) {
// mockHorses();
// }
showResult.value = false;
finalRankList.value = [];
gameStarted.value = false;
......@@ -426,17 +427,18 @@ const startIntro = async () => {
gameStarted.value = true;
isGameRunning.value = true;
if (horses.value.length === 0) {
const count = 8 + Math.floor(Math.random() * 3);
const mockPlayers: Player[] = Array.from({ length: count }, (_, i) => ({
userid: `auto-${i}`,
nickname: mockNicknames[i] || `马匹${i + 1}`,
avatar: mockAvatars[i] || '',
score: Math.floor(Math.random() * 60) + 10,
}));
updateHorses(mockPlayers);
console.log('[game4 Rank1View] 生成', count, '匹默认马');
}
// 本地模拟已关闭,如需开启请取消以下注释
// if (horses.value.length === 0) {
// const count = 8 + Math.floor(Math.random() * 3);
// const mockPlayers: Player[] = Array.from({ length: count }, (_, i) => ({
// userid: `auto-${i}`,
// nickname: mockNicknames[i] || `马匹${i + 1}`,
// avatar: mockAvatars[i] || '',
// score: Math.floor(Math.random() * 60) + 10,
// }));
// updateHorses(mockPlayers);
// console.log('[game4 Rank1View] 生成', count, '匹默认马');
// }
startGameLoop();
if ($is_local_mode()) {
......
......@@ -33,7 +33,8 @@ const emptyRankPlayer = (index: number): Player => ({
})
const screen = ref<GameScreen>('loading')
// 本地模式下使用模拟玩家数据
// 本地模式下使用模拟玩家数据(已关闭)
const mockPlayers = [
{ userid: 'local-1', nickname: '疾风骑士', avatar: 'https://api.dicebear.com/9.x/fun-emoji/svg?seed=Felix', score: 45 },
{ userid: 'local-2', nickname: '闪电侠', avatar: 'https://api.dicebear.com/9.x/fun-emoji/svg?seed=Aneka', score: 38 },
......@@ -47,11 +48,7 @@ const mockPlayers = [
{ userid: 'local-10', nickname: '踏雪无痕', avatar: 'https://api.dicebear.com/9.x/fun-emoji/svg?seed=Tiger', score: 18 },
];
const loadingPlayers = ref<any[]>(
$is_local_mode()
? mockPlayers
: Array.from({ length: PLAYER_LIMIT }, emptyLoadingPlayer)
)
const loadingPlayers = ref<any[]>(Array.from({ length: PLAYER_LIMIT }, emptyLoadingPlayer))
const playerCount = ref(0)
const rankPlayers = ref<Player[]>(Array.from({ length: RANK_LIMIT }, (_, index) => emptyRankPlayer(index)))
const rank1Ref = ref<InstanceType<typeof Rank1> | null>(null)
......@@ -185,13 +182,7 @@ const startGameWithMusic = () => {
// 确保背景音乐播放
playGame5Music()
// 本地调试模式:跳过 WebSocket,直接进入游戏画面
if ($is_local_mode()) {
console.log('[Game5] 本地模式,直接进入游戏画面')
gotoRank1WithIntro()
return
}
if (playerCount.value == 0) {
$toast('房间中没有玩家');
return;
......@@ -203,12 +194,7 @@ const nextRound = () => {
// 立刻停止喝彩音乐并移除指针事件监听,防止点击按钮时重新触发 playApplauseMusic
stopApplauseMusic()
if ($is_local_mode()) {
// 本地模式:回到 loading 页,用户点击"开始挑战"后再进入游戏
gotoLoading(true)
return
}
gotoLoading(true)
// 等待组件卸载完成后再确保 BGM 播放
nextTick().then(() => playGame5Music())
......@@ -234,12 +220,7 @@ const backHandler = async() => {
// 立刻停止喝彩音乐并移除指针事件监听,防止点击按钮时重新触发 playApplauseMusic
stopApplauseMusic()
if ($is_local_mode()) {
stopAllMusic()
router.replace('/main')
return
}
const ok = await $confirm({
title: '提示',
message: '是否关闭当前房间回到首页',
......
......@@ -227,7 +227,8 @@ const generateRandomHorses = () => {
horses.value = newHorses;
};
// ========== 本地模拟数据(参考 game3)==========
// ========== 本地模拟数据(已关闭)==========
const mockAvatars = [
'https://api.dicebear.com/9.x/fun-emoji/svg?seed=Felix',
'https://api.dicebear.com/9.x/fun-emoji/svg?seed=Aneka',
......@@ -266,14 +267,14 @@ const preloadHorseFrames = () => {
onMounted(() => {
preloadHorseFrames();
if ($is_run_local()) {
// 使用模拟玩家数据更新排名列表
updateRankList(mockPlayers);
gameStarted.value = true;
isGameRunning.value = true;
generateRandomHorses();
startHorseLoop();
}
// 本地模拟已关闭,如需开启请取消以下注释
// if ($is_run_local()) {
// updateRankList(mockPlayers);
// gameStarted.value = true;
// isGameRunning.value = true;
// generateRandomHorses();
// startHorseLoop();
// }
});
onUnmounted(() => {
......
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