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

fix: h5 game的摇一摇在oss失效问题;

parent 7b089924
...@@ -8,6 +8,15 @@ const game6Music1Url = assetUrl('game6_1.mp3') ...@@ -8,6 +8,15 @@ const game6Music1Url = assetUrl('game6_1.mp3')
const game6Music2Url = assetUrl('game6_2.mp3') const game6Music2Url = assetUrl('game6_2.mp3')
const go321 = assetUrl('321go.mp3') const go321 = assetUrl('321go.mp3')
console.log('[Music] 音频文件路径:')
console.log(' game1:', game1MusicUrl)
console.log(' game2:', game2MusicUrl)
console.log(' game3_1 (金币):', game3Music1Url)
console.log(' game3_2 (炸弹):', game3Music2Url)
console.log(' game6_1:', game6Music1Url)
console.log(' game6_2:', game6Music2Url)
console.log(' 321go:', go321)
const effectTemplates = new Map<string, HTMLAudioElement>() const effectTemplates = new Map<string, HTMLAudioElement>()
const playingEffects = new Set<HTMLAudioElement>() const playingEffects = new Set<HTMLAudioElement>()
......
...@@ -276,7 +276,7 @@ onMounted(() => { ...@@ -276,7 +276,7 @@ onMounted(() => {
console.log('[Game4 H5] 本地模式:2秒后自动开始游戏'); console.log('[Game4 H5] 本地模式:2秒后自动开始游戏');
setTimeout(() => { setTimeout(() => {
startGameView(); startGameView();
}, 2000); }, 3000);
} }
}); });
......
...@@ -146,7 +146,7 @@ onMounted(() => { ...@@ -146,7 +146,7 @@ onMounted(() => {
.txt-loading { .txt-loading {
position: absolute; position: absolute;
top: 743px; top: 724px;
left: 50%; left: 50%;
width: 288px; width: 288px;
color: #e00000; color: #e00000;
......
...@@ -3,6 +3,7 @@ import { onBeforeUnmount, onMounted, ref } from 'vue' ...@@ -3,6 +3,7 @@ import { onBeforeUnmount, onMounted, ref } from 'vue'
import { assetUrl } from '@/commons/assets' import { assetUrl } from '@/commons/assets'
const shakeSound = assetUrl('game4/yaoyiyao.mp3') const shakeSound = assetUrl('game4/yaoyiyao.mp3')
console.log('[摇一摇] 音频文件路径:', shakeSound)
const props = defineProps<{ const props = defineProps<{
imageUrls: Record<string, string> imageUrls: Record<string, string>
...@@ -37,8 +38,8 @@ let lastPosition = { ...@@ -37,8 +38,8 @@ let lastPosition = {
// 是否正在摇晃(用于停止检测) // 是否正在摇晃(用于停止检测)
let wasShaking = false let wasShaking = false
let audioContext: AudioContext | null = null // 使用 Audio 元素播放音效(避免 CORS 问题)
let shakeAudioBuffer: AudioBuffer | null = null let shakeAudio: HTMLAudioElement | null = null
// iOS 13+/iPadOS 需要主动请求 DeviceMotion 权限 // iOS 13+/iPadOS 需要主动请求 DeviceMotion 权限
let motionPermissionGranted = false let motionPermissionGranted = false
...@@ -73,63 +74,56 @@ const requestMotionPermission = async (): Promise<boolean> => { ...@@ -73,63 +74,56 @@ const requestMotionPermission = async (): Promise<boolean> => {
const initAudio = async () => { const initAudio = async () => {
try { try {
audioContext = new (window.AudioContext || (window as any).webkitAudioContext)() console.log('[摇一摇] 开始初始化音频...')
// 如果 AudioContext 处于 suspended 状态,注册一次性交互监听器来激活 // 使用 Audio 元素(不受 CORS 限制)
if (audioContext.state === 'suspended') { shakeAudio = new Audio(shakeSound)
console.log('[摇一摇] AudioContext 处于 suspended 状态,注册交互监听器') const audio = shakeAudio // 保存引用,避免 null 检查
audio.preload = 'auto'
const resumeAudio = async () => { audio.volume = 1
if (audioContext && audioContext.state === 'suspended') {
await audioContext.resume() // 等待音频加载
console.log('[摇一摇] AudioContext 已通过用户交互激活') await new Promise<void>((resolve, reject) => {
} const onCanPlay = () => {
// 移除监听器 audio.removeEventListener('canplaythrough', onCanPlay)
window.removeEventListener('touchstart', resumeAudio) audio.removeEventListener('error', onError)
window.removeEventListener('click', resumeAudio) resolve()
}
const onError = (e: Event) => {
audio.removeEventListener('canplaythrough', onCanPlay)
audio.removeEventListener('error', onError)
reject(new Error('音频加载失败'))
} }
window.addEventListener('touchstart', resumeAudio, { once: true }) audio.addEventListener('canplaythrough', onCanPlay)
window.addEventListener('click', resumeAudio, { once: true }) audio.addEventListener('error', onError)
} audio.load()
})
const response = await fetch(shakeSound) console.log('[摇一摇] 音频初始化成功,使用 Audio 元素')
const arrayBuffer = await response.arrayBuffer()
shakeAudioBuffer = await audioContext.decodeAudioData(arrayBuffer)
console.log('[摇一摇] 音频初始化成功,AudioContext state:', audioContext.state)
} catch (error) { } catch (error) {
console.error('[摇一摇] 音频初始化失败:', error) console.error('[摇一摇] 音频初始化失败:', error)
console.error('[摇一摇] 错误堆栈:', (error as Error).stack)
} }
} }
const playShakeSound = () => { const playShakeSound = () => {
if (!audioContext || !shakeAudioBuffer) { if (!shakeAudio) {
console.warn('[摇一摇] 音频未初始化,无法播放') console.warn('[摇一摇] 音频未初始化,无法播放')
return return
} }
// 确保 AudioContext 处于运行状态 try {
if (audioContext.state === 'suspended') { // 重置播放位置并播放
audioContext.resume().then(() => { shakeAudio.currentTime = 0
console.log('[摇一摇] AudioContext 已恢复') shakeAudio.play().catch(err => {
playShakeSoundInternal() console.error('[摇一摇] 音频播放失败:', err)
}).catch(err => {
console.error('[摇一摇] AudioContext 恢复失败:', err)
}) })
} else { } catch (error) {
playShakeSoundInternal() console.error('[摇一摇] 播放音效出错:', error)
} }
} }
const playShakeSoundInternal = () => {
if (!audioContext || !shakeAudioBuffer) return
const source = audioContext.createBufferSource()
source.buffer = shakeAudioBuffer
source.connect(audioContext.destination)
source.start(0)
}
const handleDeviceMotion = (ev: DeviceMotionEvent) => { const handleDeviceMotion = (ev: DeviceMotionEvent) => {
const nowTime = Date.now() const nowTime = Date.now()
const motion = ev.accelerationIncludingGravity const motion = ev.accelerationIncludingGravity
...@@ -208,8 +202,9 @@ onMounted(async () => { ...@@ -208,8 +202,9 @@ onMounted(async () => {
onBeforeUnmount(() => { onBeforeUnmount(() => {
window.removeEventListener('devicemotion', handleDeviceMotion) window.removeEventListener('devicemotion', handleDeviceMotion)
if (audioContext) { if (shakeAudio) {
audioContext.close() shakeAudio.pause()
shakeAudio = null
} }
if (yaoyiyaoShakeTimer) { if (yaoyiyaoShakeTimer) {
clearTimeout(yaoyiyaoShakeTimer) clearTimeout(yaoyiyaoShakeTimer)
...@@ -218,12 +213,7 @@ onBeforeUnmount(() => { ...@@ -218,12 +213,7 @@ onBeforeUnmount(() => {
// 点击马触发:iOS 先请求权限(不触发得分) // 点击马触发:iOS 先请求权限(不触发得分)
const onTapHorse = async () => { const onTapHorse = async () => {
// 激活 AudioContext(解决浏览器自动播放策略)
if (audioContext && audioContext.state === 'suspended') {
await audioContext.resume()
console.log('[摇一摇] 通过点击激活 AudioContext')
}
if (!motionPermissionGranted) { if (!motionPermissionGranted) {
await requestMotionPermission() await requestMotionPermission()
showIOSHint.value = false showIOSHint.value = false
......
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