Commit 8e748bdc authored by 董政锦's avatar 董政锦

fix: 修复game5背景音乐逻辑;加本地测试数据;

parent 902e3273
...@@ -6,8 +6,8 @@ import Rank1 from './views/Rank1View.vue' ...@@ -6,8 +6,8 @@ import Rank1 from './views/Rank1View.vue'
import Rank2 from './views/Rank2View.vue' import Rank2 from './views/Rank2View.vue'
import { useAdminGameSocket } from '@/composables/useAdminGameSocket' import { useAdminGameSocket } from '@/composables/useAdminGameSocket'
import type Player from '@/commons/player.ts' import type Player from '@/commons/player.ts'
import { playApplauseMusic, playGame5Music, stopAllMusic, stopGame5Music } from '@/commons/music' import { playApplauseMusic, playGame5Music, stopAllMusic, stopApplauseMusic, stopGame5Music } from '@/commons/music'
import { $confirm, $remove_socket_storage, $notify, $toast } from '@/commons/utils.ts' import { $confirm, $is_local_mode, $remove_socket_storage, $notify, $toast } from '@/commons/utils.ts'
const router = useRouter() const router = useRouter()
...@@ -33,7 +33,25 @@ const emptyRankPlayer = (index: number): Player => ({ ...@@ -33,7 +33,25 @@ const emptyRankPlayer = (index: number): Player => ({
}) })
const screen = ref<GameScreen>('loading') const screen = ref<GameScreen>('loading')
const loadingPlayers = ref<any[]>(Array.from({ length: PLAYER_LIMIT }, emptyLoadingPlayer)) // 本地模式下使用模拟玩家数据
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 },
{ userid: 'local-3', nickname: '追风者', avatar: 'https://api.dicebear.com/9.x/fun-emoji/svg?seed=Salem', score: 30 },
{ userid: 'local-4', nickname: '千里马', avatar: 'https://api.dicebear.com/9.x/fun-emoji/svg?seed=Midnight', score: 22 },
{ userid: 'local-5', nickname: '飞毛腿', avatar: 'https://api.dicebear.com/9.x/fun-emoji/svg?seed=Lucky', score: 15 },
{ userid: 'local-6', nickname: '烈焰驹', avatar: 'https://api.dicebear.com/9.x/fun-emoji/svg?seed=Bandit', score: 52 },
{ userid: 'local-7', nickname: '暴风战士', avatar: 'https://api.dicebear.com/9.x/fun-emoji/svg?seed=Misty', score: 41 },
{ userid: 'local-8', nickname: '神行者', avatar: 'https://api.dicebear.com/9.x/fun-emoji/svg?seed=Pepper', score: 35 },
{ userid: 'local-9', nickname: '银鞍客', avatar: 'https://api.dicebear.com/9.x/fun-emoji/svg?seed=Oreo', score: 28 },
{ 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 playerCount = ref(0) const playerCount = ref(0)
const rankPlayers = ref<Player[]>(Array.from({ length: RANK_LIMIT }, (_, index) => emptyRankPlayer(index))) const rankPlayers = ref<Player[]>(Array.from({ length: RANK_LIMIT }, (_, index) => emptyRankPlayer(index)))
const rank1Ref = ref<InstanceType<typeof Rank1> | null>(null) const rank1Ref = ref<InstanceType<typeof Rank1> | null>(null)
...@@ -108,6 +126,8 @@ const gotoRank1WithIntro = async () => { ...@@ -108,6 +126,8 @@ const gotoRank1WithIntro = async () => {
isPlayingStartAnimation = true isPlayingStartAnimation = true
seedRankPlayersFromLoading() seedRankPlayersFromLoading()
// 进入游戏画面前确保背景音乐播放中
playGame5Music()
screen.value = 'rank1' screen.value = 'rank1'
await nextTick() await nextTick()
await rank1Ref.value?.startIntro() await rank1Ref.value?.startIntro()
...@@ -162,23 +182,41 @@ const { startGame, createRoom, closeRoom, backRoom } = useAdminGameSocket({ ...@@ -162,23 +182,41 @@ const { startGame, createRoom, closeRoom, backRoom } = useAdminGameSocket({
}) })
const startGameWithMusic = () => { const startGameWithMusic = () => {
// 确保背景音乐播放
playGame5Music()
// 本地调试模式:跳过 WebSocket,直接进入游戏画面
if ($is_local_mode()) {
console.log('[Game5] 本地模式,直接进入游戏画面')
gotoRank1WithIntro()
return
}
if (playerCount.value == 0) { if (playerCount.value == 0) {
// alert('房间中没有玩家')
$toast('房间中没有玩家'); $toast('房间中没有玩家');
return; return;
} }
playGame5Music()
startGame() startGame()
} }
const nextRound = () => { const nextRound = () => {
// 立刻停止喝彩音乐并移除指针事件监听,防止点击按钮时重新触发 playApplauseMusic
stopApplauseMusic()
if ($is_local_mode()) {
// 本地模式:回到 loading 页,用户点击"开始挑战"后再进入游戏
gotoLoading(true)
return
}
gotoLoading(true) gotoLoading(true)
// 等待组件卸载完成后再确保 BGM 播放
nextTick().then(() => playGame5Music())
//重开房间 //重开房间
backRoom(5) backRoom(5)
} }
const nextRoundWithMusic = () => { const nextRoundWithMusic = () => {
playGame5Music()
nextRound() nextRound()
} }
...@@ -193,6 +231,15 @@ onUnmounted(() => { ...@@ -193,6 +231,15 @@ onUnmounted(() => {
}) })
const backHandler = async() => { const backHandler = async() => {
// 立刻停止喝彩音乐并移除指针事件监听,防止点击按钮时重新触发 playApplauseMusic
stopApplauseMusic()
if ($is_local_mode()) {
stopAllMusic()
router.replace('/main')
return
}
const ok = await $confirm({ const ok = await $confirm({
title: '提示', title: '提示',
message: '是否关闭当前房间回到首页', message: '是否关闭当前房间回到首页',
......
...@@ -38,7 +38,7 @@ const imageUrls = { ...@@ -38,7 +38,7 @@ const imageUrls = {
const HORSE_TYPES = [1, 2, 3, 4] as const; const HORSE_TYPES = [1, 2, 3, 4] as const;
const HORSE_FRAME_COUNT = 21; // 每匹马 21 帧(00-20) const HORSE_FRAME_COUNT = 21; // 每匹马 21 帧(00-20)
const HORSE_WIDTH = 200; const HORSE_WIDTH = 200;
const HORSE_START_X = -330; // 左侧屏外起点 const HORSE_START_X = -100; // 左侧屏外起点,进一步右移让马更快进入屏幕
const HORSE_END_X = 1920 - HORSE_WIDTH; // 右边缘贴齐屏幕右侧(1720px) const HORSE_END_X = 1920 - HORSE_WIDTH; // 右边缘贴齐屏幕右侧(1720px)
...@@ -67,9 +67,9 @@ let horseIdCounter = 0; ...@@ -67,9 +67,9 @@ let horseIdCounter = 0;
const isGameRunning = ref(false); const isGameRunning = ref(false);
const emptyPlayer = (index: number): Player => ({ const emptyPlayer = (index: number): Player => ({
wechat_id: `empty-${index}`, wechat_id: `empty-${index}`,
nickname: "-", nickname: "虚位以待",
avatar: "", avatar: "",
score: 0, score: "-",
}); });
const list = ref<Player[]>( const list = ref<Player[]>(
...@@ -210,8 +210,8 @@ const generateRandomHorses = () => { ...@@ -210,8 +210,8 @@ const generateRandomHorses = () => {
for (let i = 0; i < count; i++) { for (let i = 0; i < count; i++) {
const type = HORSE_TYPES[i % HORSE_TYPES.length]!; const type = HORSE_TYPES[i % HORSE_TYPES.length]!;
const lane = lanes[i % 2]!; const lane = lanes[i % 2]!;
const delayMs = i * 2500 + Math.random() * 1000; // 每匹马间隔2.5秒起步,加随机1秒 const delayMs = i * 50 + Math.random() * 50; // 大幅减少起步延迟,第一匹马几乎立刻出现
const durationMs = (40 + Math.random() * 40) * 1000; // 40-80秒,速度浮动更大 const durationMs = (60 + Math.random() * 40) * 1000; // 60-100秒,降低速度,让马跑得更慢
newHorses.push({ newHorses.push({
id: `horse-${++horseIdCounter}`, id: `horse-${++horseIdCounter}`,
horseType: type, horseType: type,
...@@ -227,6 +227,33 @@ const generateRandomHorses = () => { ...@@ -227,6 +227,33 @@ const generateRandomHorses = () => {
horses.value = newHorses; 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',
'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',
];
const mockPlayers: 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 },
{ 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 preloadHorseFrames = () => { const preloadHorseFrames = () => {
for (const frames of Object.values(horseFrames)) { for (const frames of Object.values(horseFrames)) {
...@@ -240,6 +267,8 @@ const preloadHorseFrames = () => { ...@@ -240,6 +267,8 @@ const preloadHorseFrames = () => {
onMounted(() => { onMounted(() => {
preloadHorseFrames(); preloadHorseFrames();
if ($is_run_local()) { if ($is_run_local()) {
// 使用模拟玩家数据更新排名列表
updateRankList(mockPlayers);
gameStarted.value = true; gameStarted.value = true;
isGameRunning.value = true; isGameRunning.value = true;
generateRandomHorses(); generateRandomHorses();
...@@ -525,11 +554,11 @@ const rankIcon = (index: number) => { ...@@ -525,11 +554,11 @@ const rankIcon = (index: number) => {
} }
.horse-wrapper.horse-lane-top { .horse-wrapper.horse-lane-top {
bottom: 350px; bottom: 300px; /* 往下挪 50px */
} }
.horse-wrapper.horse-lane-bottom { .horse-wrapper.horse-lane-bottom {
bottom: 60px; bottom: 110px; /* 往上挪 50px */
} }
......
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