Commit 57143944 authored by 陈冲's avatar 陈冲

添加游戏说明,h5击鼓播放音乐

parent 03def38d
import game1MusicUrl from '@/assets/images/game1.mp3'
let backgroundMusic: HTMLAudioElement | null = null
function getBackgroundMusic() {
if (!backgroundMusic) {
backgroundMusic = new Audio(game1MusicUrl)
backgroundMusic.loop = true
backgroundMusic.preload = 'auto'
backgroundMusic.volume = 0.6
backgroundMusic.load()
}
return backgroundMusic
}
export async function playGame1Music() {
const audio = getBackgroundMusic()
try {
await audio.play()
window.removeEventListener('pointerdown', playGame1Music)
window.removeEventListener('keydown', playGame1Music)
} catch {
window.addEventListener('pointerdown', playGame1Music, { once: true })
window.addEventListener('keydown', playGame1Music, { once: true })
}
}
export function stopGame1Music() {
window.removeEventListener('pointerdown', playGame1Music)
window.removeEventListener('keydown', playGame1Music)
backgroundMusic?.pause()
}
...@@ -6,13 +6,15 @@ const props = withDefaults(defineProps<{ ...@@ -6,13 +6,15 @@ const props = withDefaults(defineProps<{
width?: number width?: number
height?: number height?: number
mode?: 'contain' | 'cover' mode?: 'contain' | 'cover'
backgroundMode?: 'contain' | 'cover' backgroundMode?: 'contain' | 'cover',
showGameRule?: boolean,
}>(), { }>(), {
background: 'linear-gradient(180deg, #fbf7ef 0%, #ffe7dc 100%)', background: 'linear-gradient(180deg, #fbf7ef 0%, #ffe7dc 100%)',
width: 750, width: 750,
height: 1624, height: 1624,
mode: 'contain', mode: 'contain',
backgroundMode: 'cover', backgroundMode: 'cover',
showGameRule: false
}) })
const emit = defineEmits<{ const emit = defineEmits<{
...@@ -141,14 +143,17 @@ defineExpose({ ...@@ -141,14 +143,17 @@ defineExpose({
</script> </script>
<template> <template>
<main class="mobile-stage-viewport"> <main class="mobile-stage-viewport">
<div class="mobile-stage-background" :style="backgroundStyle" /> <div class="mobile-stage-background" :style="backgroundStyle" />
<div class="mobile-stage" :style="stageStyle"> <div class="mobile-stage" :style="stageStyle">
<slot /> <slot />
</div> </div>
<div v-if="countdownVisible" class="countdown-modal"> <div v-if="countdownVisible" class="modal-container">
<div :key="countdownKey" class="countdown-number">{{ countdown }}</div> <div :key="countdownKey" class="countdown-number">{{ countdown }}</div>
</div> </div>
<div v-else-if="showGameRule" class="modal-container">
<slot name="gameRule" ></slot>
</div>
</main> </main>
</template> </template>
...@@ -174,7 +179,7 @@ defineExpose({ ...@@ -174,7 +179,7 @@ defineExpose({
z-index: 1; z-index: 1;
} }
.countdown-modal { .modal-container {
position: absolute; position: absolute;
inset: 0; inset: 0;
z-index: 10; z-index: 10;
...@@ -182,7 +187,7 @@ defineExpose({ ...@@ -182,7 +187,7 @@ defineExpose({
align-items: center; align-items: center;
justify-content: center; justify-content: center;
background-color: rgba(0, 0, 0, 0.2); background-color: rgba(0, 0, 0, 0.2);
pointer-events: none; /* pointer-events: none; */
} }
.countdown-number { .countdown-number {
......
...@@ -7,6 +7,7 @@ import LoadingView from './views/LoadingView.vue' ...@@ -7,6 +7,7 @@ import LoadingView from './views/LoadingView.vue'
import PlayingView from './views/PlayingView.vue' import PlayingView from './views/PlayingView.vue'
import ScoreView from './views/ScoreView.vue' import ScoreView from './views/ScoreView.vue'
import { $getWechat } from '@/commons/utils.ts' import { $getWechat } from '@/commons/utils.ts'
import { playGame1Music } from '@/commons/music'
type GameView = 'loading' | 'playing' | 'score' type GameView = 'loading' | 'playing' | 'score'
...@@ -15,7 +16,7 @@ const imageUrls = { ...@@ -15,7 +16,7 @@ const imageUrls = {
bg2: cssAssetUrl('game1/bg2.png'), bg2: cssAssetUrl('game1/bg2.png'),
logo: cssAssetUrl('game1/logo.png'), logo: cssAssetUrl('game1/logo.png'),
title: cssAssetUrl('game1/title.png'), title: cssAssetUrl('game1/title.png'),
avatar: cssAssetUrl('game1/avatar.png'), avatar: cssAssetUrl('avatar.png'),
gu: cssAssetUrl('game1/gu.png'), gu: cssAssetUrl('game1/gu.png'),
clock: cssAssetUrl('game1/clock.png'), clock: cssAssetUrl('game1/clock.png'),
gu01: cssAssetUrl('game1/gu01.png'), gu01: cssAssetUrl('game1/gu01.png'),
...@@ -24,6 +25,7 @@ const imageUrls = { ...@@ -24,6 +25,7 @@ const imageUrls = {
scoreBg: cssAssetUrl('game1/score-bg.png'), scoreBg: cssAssetUrl('game1/score-bg.png'),
back: cssAssetUrl('game1/back.png'), back: cssAssetUrl('game1/back.png'),
replay: cssAssetUrl('game1/replay.png'), replay: cssAssetUrl('game1/replay.png'),
close: cssAssetUrl('game1/close.png'),
} }
const wechat = $getWechat() const wechat = $getWechat()
...@@ -38,9 +40,10 @@ const isGuPlaying = ref(false) ...@@ -38,9 +40,10 @@ const isGuPlaying = ref(false)
const token = ref(wechat?.token ?? '') const token = ref(wechat?.token ?? '')
const nickname = ref(wechat?.nickname ?? '') const nickname = ref(wechat?.nickname ?? '')
const avatar = ref(wechat?.avatar ?? '') const avatar = ref(wechat?.avatar ?? '')
const showGameRule = ref(false)
const mobileStageRef = ref<InstanceType<typeof MobileStage> | null>(null) const mobileStageRef = ref<InstanceType<typeof MobileStage> | null>(null)
const _offSocketMessage = ref<(() => void) | undefined>() const _offSocketMessage = ref<(() => void) | undefined>()
let guFrameTimer: ReturnType<typeof window.setTimeout> | undefined let guFrameTimer: ReturnType<typeof window.setTimeout> | undefined
let gameCountdownTimer: ReturnType<typeof window.setTimeout> | undefined let gameCountdownTimer: ReturnType<typeof window.setTimeout> | undefined
...@@ -160,6 +163,7 @@ const touchHandler = () => { ...@@ -160,6 +163,7 @@ const touchHandler = () => {
tick.value += 1 tick.value += 1
submitScore() submitScore()
playGame1Music();
isGuPlaying.value = true isGuPlaying.value = true
let frameIndex = 0 let frameIndex = 0
...@@ -194,6 +198,7 @@ if (wechat) { ...@@ -194,6 +198,7 @@ if (wechat) {
}, 200) }, 200)
}, },
onGameStart: async () => { onGameStart: async () => {
showGameRule.value = false;
await mobileStageRef.value?.startCountdown() await mobileStageRef.value?.startCountdown()
startGameView() startGameView()
}, },
...@@ -231,11 +236,31 @@ onBeforeUnmount(() => { ...@@ -231,11 +236,31 @@ onBeforeUnmount(() => {
window.removeEventListener('beforeunload', confirmRefresh) window.removeEventListener('beforeunload', confirmRefresh)
} }
}) })
const showGameRuleHandler = () => {
showGameRule.value = !showGameRule.value;
}
</script> </script>
<template> <template>
<MobileStage v-if="token" ref="mobileStageRef" :background="`${imageUrls.bg} center/cover`"> <MobileStage v-if="token" :showGameRule="showGameRule" ref="mobileStageRef"
<LoadingView v-if="currentView === 'loading'" :image-urls="imageUrls" :user-join-status="userJoinStatus" /> :background="`${imageUrls.bg} center/cover`">
<template #gameRule>
<div class="rule-container">
<div class="rule-txt-container">
<div class="rule-title">游戏规则</div>
<div class="rule-txt">
微信用户通过扫描大屏幕二维码
参与,可容纳多人同时进行且比拼骑马(摇一摇)速度谁最快即为获胜,游戏结束按分值高低先后排名,有机会获得新疆福彩定制周边礼品一份。
</div>
</div>
<div class="rule-close">
<div @click="showGameRuleHandler"></div>
</div>
</div>
</template>
<LoadingView v-if="currentView === 'loading'" :image-urls="imageUrls" :user-join-status="userJoinStatus"
@touchGameRule="showGameRuleHandler" />
<PlayingView v-else-if="currentView === 'playing'" :image-urls="imageUrls" :tick="tick" :rank="rank" <PlayingView v-else-if="currentView === 'playing'" :image-urls="imageUrls" :tick="tick" :rank="rank"
:current-gu="currentGu" :countdown-interval="countdownInterval" :is-div-desc-visible="isDivDescVisible" :current-gu="currentGu" :countdown-interval="countdownInterval" :is-div-desc-visible="isDivDescVisible"
@touch="touchHandler" /> @touch="touchHandler" />
...@@ -246,3 +271,43 @@ onBeforeUnmount(() => { ...@@ -246,3 +271,43 @@ onBeforeUnmount(() => {
请使用微信扫码进入游戏 请使用微信扫码进入游戏
</div> </div>
</template> </template>
<style scoped>
.rule-container {
.rule-txt-container {
background: #FFF9E4;
margin-left: 20px;
margin-right: 20px;
border-radius: 5px;
padding-top: 20px;
padding-bottom: 10px;
.rule-title {
text-align: center;
color: #850000;
font-weight: bold;
}
.rule-txt {
font-size: 12pt;
padding: 10px;
margin-top: 10px;
}
}
.rule-close {
width: 32px;
height: 130px;
margin: 0 auto;
background: v-bind('imageUrls.close') center/cover;
position: relative;
>div {
position: absolute;
bottom: 0;
width: 32px;
height: 32px;
border-radius: 16px;
}
}
}
</style>
\ No newline at end of file
...@@ -17,7 +17,7 @@ onMounted(() => { ...@@ -17,7 +17,7 @@ onMounted(() => {
<template> <template>
<div class="h5-page game-stage"> <div class="h5-page game-stage">
<div class="game-desc">游戏规则</div> <div class="game-desc" @click="$emit('touchGameRule')">游戏规则</div>
<div class="img-logo"></div> <div class="img-logo"></div>
<div class="img-title"></div> <div class="img-title"></div>
<div class="img-avatar" :style="`background: url(${avatar});border-radius:66px;width:132px;height:132px;`"></div> <div class="img-avatar" :style="`background: url(${avatar});border-radius:66px;width:132px;height:132px;`"></div>
......
...@@ -38,12 +38,12 @@ export default defineConfig(({ command }) => ({ ...@@ -38,12 +38,12 @@ export default defineConfig(({ command }) => ({
server: { server: {
proxy: { proxy: {
'/socket.io': { '/socket.io': {
target: 'http://192.168.1.23:8082', target: 'http://localhost:8082',
changeOrigin: true, changeOrigin: true,
ws: true, ws: true,
}, },
'/manager': { '/manager': {
target: 'http://192.168.1.23:8082', target: 'http://localhost:8082',
changeOrigin: true, changeOrigin: true,
}, },
}, },
......
...@@ -39,12 +39,12 @@ export default defineConfig(({ command }) => ({ ...@@ -39,12 +39,12 @@ export default defineConfig(({ command }) => ({
server: { server: {
proxy: { proxy: {
'/socket.io': { '/socket.io': {
target: 'http://192.168.1.23:8082', target: 'http://localhost:8082',
changeOrigin: true, changeOrigin: true,
ws: true, ws: true,
}, },
'/manager': { '/manager': {
target: 'http://192.168.1.23:8082', target: 'http://localhost:8082',
changeOrigin: true, changeOrigin: true,
}, },
}, },
......
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