Commit 50759d94 authored by 董政锦's avatar 董政锦

feat: game3 初版完成;

parent 0d467745
...@@ -5,7 +5,7 @@ import MobileStage from '@/components/MobileStage.vue' ...@@ -5,7 +5,7 @@ import MobileStage from '@/components/MobileStage.vue'
import { useGameSocket, joinSharedRoom, sendGameMessage, userJoinStatus } from '@/composables/useGameSocket' import { useGameSocket, joinSharedRoom, sendGameMessage, userJoinStatus } from '@/composables/useGameSocket'
import LoadingView from './views/LoadingView.vue' import LoadingView from './views/LoadingView.vue'
import PlayingView from './views/PlayingView.vue' import PlayingView from './views/PlayingView.vue'
import { $getWechat, $toast } from '@/commons/utils.ts' import { $getWechat, $toast, $is_run_local } from '@/commons/utils.ts'
import { playGame6Music, stopGame6Music } from '@/commons/music'; import { playGame6Music, stopGame6Music } from '@/commons/music';
type GameView = 'loading' | 'playing' type GameView = 'loading' | 'playing'
...@@ -19,6 +19,8 @@ type RankPlayer = { ...@@ -19,6 +19,8 @@ type RankPlayer = {
const imageUrls: Record<string, string> = { const imageUrls: Record<string, string> = {
bg: cssAssetUrl('game3/bg.webp'), bg: cssAssetUrl('game3/bg.webp'),
bg3: cssAssetUrl('game3/bg3.webp'), bg3: cssAssetUrl('game3/bg3.webp'),
left: cssAssetUrl('game3/icon_zuo.webp'),
right: cssAssetUrl('game3/icon_you.webp'),
bg4: cssAssetUrl('game3/pic_paodao.webp'), bg4: cssAssetUrl('game3/pic_paodao.webp'),
logo: cssAssetUrl('logo.png'), logo: cssAssetUrl('logo.png'),
loadingBg1: cssAssetUrl('game6/loadingbg1.png'), loadingBg1: cssAssetUrl('game6/loadingbg1.png'),
...@@ -44,6 +46,7 @@ const wechat = $getWechat() ...@@ -44,6 +46,7 @@ const wechat = $getWechat()
const currentView = ref<GameView>('loading') const currentView = ref<GameView>('loading')
const countdownInterval = ref(60) const countdownInterval = ref(60)
const isDivDescVisible = ref(false) const isDivDescVisible = ref(false)
const isGameOver = ref(false)
const score = ref(0) const score = ref(0)
const rank = ref(0) //排名 const rank = ref(0) //排名
const rankList = ref<RankPlayer[]>([]) const rankList = ref<RankPlayer[]>([])
...@@ -74,6 +77,7 @@ const nickname = ref(wechat?.nickname ?? '') ...@@ -74,6 +77,7 @@ const nickname = ref(wechat?.nickname ?? '')
const avatar = ref(wechat?.avatar ?? '') const avatar = ref(wechat?.avatar ?? '')
const showGameRule = ref(true) const showGameRule = ref(true)
const showGameRank = ref(false) const showGameRank = ref(false)
const isLocalMode = $is_run_local()
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>()
...@@ -97,19 +101,25 @@ function stopGameCountdown() { ...@@ -97,19 +101,25 @@ function stopGameCountdown() {
} }
function submitScore(save: boolean = false, currentTick = score.value) { function submitScore(save: boolean = false, currentTick = score.value) {
//最后提交保存在数据库中 if (!wechat && !isLocalMode) return
if (save) { if (save) {
//item_num 游戏项目(1到6) if (isLocalMode && !wechat) {
//wechat 原始token console.log('[game3 本地模式] 提交最终分数:', currentTick)
return
}
sendGameMessage('submit_score_save', { sendGameMessage('submit_score_save', {
score: currentTick, score: currentTick,
wechat: wechat.token_origin, wechat: wechat.token_origin,
item_num: 6, item_num: 3,
nickname: wechat.nickname, nickname: wechat.nickname,
avatar: wechat.avatar, avatar: wechat.avatar,
rank: rank.value, rank: rank.value,
}) })
} else { } else {
if (isLocalMode && !wechat) {
console.log('[game3 本地模式] 实时分数:', currentTick)
return
}
sendGameMessage('submit_score', { score: currentTick }) sendGameMessage('submit_score', { score: currentTick })
} }
} }
...@@ -147,8 +157,8 @@ function resetToLoadingView() { ...@@ -147,8 +157,8 @@ function resetToLoadingView() {
rank.value = 0 rank.value = 0
rankList.value = [] rankList.value = []
countdownInterval.value = 60 countdownInterval.value = 60
// currentGu.value = guFrames[0]
isGuPlaying.value = false isGuPlaying.value = false
isGameOver.value = false
userJoinStatus.value = false userJoinStatus.value = false
showGameRank.value = false showGameRank.value = false
currentView.value = 'loading' currentView.value = 'loading'
...@@ -160,7 +170,7 @@ function startGameView() { ...@@ -160,7 +170,7 @@ function startGameView() {
score.value = 0 score.value = 0
rank.value = 0 rank.value = 0
rankList.value = [] rankList.value = []
// currentGu.value = guFrames[0] isGameOver.value = false
showGameRank.value = false showGameRank.value = false
currentView.value = 'playing' currentView.value = 'playing'
startGameCountdown() startGameCountdown()
...@@ -169,21 +179,32 @@ function startGameView() { ...@@ -169,21 +179,32 @@ function startGameView() {
function showGameOverRank() { function showGameOverRank() {
stopGameCountdown() stopGameCountdown()
setDivDescVisible(false) setDivDescVisible(false)
currentView.value = 'loading' // 保持在 playing 视图,结果页由 PlayingView 内部渲染
showGameRank.value = true isGameOver.value = true
userJoinStatus.value = false; userJoinStatus.value = false
if (isLocalMode && !wechat) {
console.log('[game3 本地模式] 游戏结束,最终分数:', score.value)
}
} }
const touchHandler = (mole: boolean) => { const touchHandler = (mole: boolean) => {
let scoreDelta = mole ? 5 : 0; let scoreDelta = mole ? 5 : -3;
let nextTick = score.value + scoreDelta let nextTick = score.value + scoreDelta
if (nextTick < 0) nextTick = 0
score.value = nextTick score.value = nextTick
if (mole) { if (mole) {
playGame6Music(1); playGame6Music(1);
submitScore(false, nextTick)
} else { } else {
playGame6Music(2); playGame6Music(2);
} }
submitScore(false, nextTick)
}
const scoreChangeHandler = (delta: number) => {
let nextTick = score.value + delta
if (nextTick < 0) nextTick = 0
score.value = nextTick
submitScore(false, nextTick)
} }
if (wechat) { if (wechat) {
...@@ -237,6 +258,7 @@ if (wechat) { ...@@ -237,6 +258,7 @@ if (wechat) {
score.value = Number.isFinite(recoveredScore) && recoveredScore > 0 ? recoveredScore : 0 score.value = Number.isFinite(recoveredScore) && recoveredScore > 0 ? recoveredScore : 0
showGameRule.value = false showGameRule.value = false
showGameRank.value = false showGameRank.value = false
isGameOver.value = false
currentView.value = 'playing' currentView.value = 'playing'
startGameCountdown( startGameCountdown(
Number.isFinite(recoveredSeconds) && recoveredSeconds > 0 ? recoveredSeconds : 0, Number.isFinite(recoveredSeconds) && recoveredSeconds > 0 ? recoveredSeconds : 0,
...@@ -263,6 +285,13 @@ onMounted(() => { ...@@ -263,6 +285,13 @@ onMounted(() => {
if (token.value) { if (token.value) {
window.addEventListener('beforeunload', confirmRefresh) window.addEventListener('beforeunload', confirmRefresh)
} }
// // TODO_LOCAL: 本地模拟游戏开始,稍后部署上线前删除此段
// if ($is_run_local()) {
// showGameRule.value = false
// currentView.value = 'playing'
// startGameCountdown()
// }
}) })
onBeforeUnmount(() => { onBeforeUnmount(() => {
...@@ -289,11 +318,13 @@ const renderBG = () => { ...@@ -289,11 +318,13 @@ const renderBG = () => {
} }
const rankCloseHandler = () => { const rankCloseHandler = () => {
showGameRank.value = false showGameRank.value = false
isGameOver.value = false
resetToLoadingView()
} }
</script> </script>
<template> <template>
<MobileStage v-if="token" :showGameRule="showGameRule" :showGameRank="showGameRank" ref="mobileStageRef" <MobileStage v-if="token || isLocalMode" :showGameRule="showGameRule" :showGameRank="showGameRank" ref="mobileStageRef"
:background="`${renderBG()}`"> :background="`${renderBG()}`">
<template #gameRule> <template #gameRule>
<div class="rule-container"> <div class="rule-container">
...@@ -345,10 +376,13 @@ const rankCloseHandler = () => { ...@@ -345,10 +376,13 @@ const rankCloseHandler = () => {
</div> </div>
<div class="img-close" @click="rankCloseHandler"></div> <div class="img-close" @click="rankCloseHandler"></div>
</template> </template>
<LoadingView v-if="currentView !== 'loading'" :image-urls="imageUrls" :user-join-status="userJoinStatus" <LoadingView v-if="currentView === 'loading'" :image-urls="imageUrls" :user-join-status="userJoinStatus"
@touchGameRule="showGameRuleHandler" /> @touchGameRule="showGameRuleHandler" />
<PlayingView v-else :image-urls="imageUrls" :tick="score" :rank="rank" :countdown-interval="countdownInterval" <PlayingView v-else :image-urls="imageUrls" :tick="score" :rank="rank" :countdown-interval="countdownInterval"
:is-div-desc-visible="isDivDescVisible" @touch="touchHandler" /> :is-div-desc-visible="isDivDescVisible" :is-game-over="isGameOver"
:rank-list="displayRankList" :user-rank="rank" :user-score="rankScore"
:user-nickname="nickname" :user-avatar="avatar"
@touch="touchHandler" @score-change="scoreChangeHandler" @rank-close="rankCloseHandler" />
</MobileStage> </MobileStage>
<div v-else style="text-align: center; width: 100vw; height: 100vh; line-height: 30; font-size: 20px;"> <div v-else style="text-align: center; width: 100vw; height: 100vh; line-height: 30; font-size: 20px;">
请使用微信扫码进入游戏 请使用微信扫码进入游戏
......
...@@ -18,7 +18,7 @@ onMounted(() => { ...@@ -18,7 +18,7 @@ onMounted(() => {
<template> <template>
<div class="h5-page game-stage"> <div class="h5-page game-stage">
<div class="game-desc" @click="$emit('touchGameRule')">游戏规则</div> <div class="game-desc" @click="$emit('touchGameRule')">游戏规则</div>
<div class="img-logo"></div> <!-- <div class="img-logo"></div> -->
<div class="img-loadingbg1">游戏等待开始倒计时60秒</div> <div class="img-loadingbg1">游戏等待开始倒计时60秒</div>
<div class="img-loadingbg2">游戏即将开始 敬请期待</div> <div class="img-loadingbg2">游戏即将开始 敬请期待</div>
<div class="txt-bottom" v-if="userJoinStatus">您已成功加入游戏<br />等待主持人开始</div> <div class="txt-bottom" v-if="userJoinStatus">您已成功加入游戏<br />等待主持人开始</div>
...@@ -33,7 +33,7 @@ onMounted(() => { ...@@ -33,7 +33,7 @@ onMounted(() => {
background: v-bind('imageUrls.loadingBg1') center/cover; background: v-bind('imageUrls.loadingBg1') center/cover;
border-radius: 45px; border-radius: 45px;
position: absolute; position: absolute;
top: 474px; top: 513px;
left: 50%; left: 50%;
margin-left: -251px; margin-left: -251px;
text-align: center; text-align: center;
......
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