Commit c6bf1726 authored by 陈冲's avatar 陈冲

修复

parent 1daec666
...@@ -32,6 +32,7 @@ const wechat = $getWechat() ...@@ -32,6 +32,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 isGameEnded = ref(false)
const tick = ref(0) //点击次数 const tick = ref(0) //点击次数
const rank = ref(0) //排名 const rank = ref(0) //排名
const roomStatus = ref(0) const roomStatus = ref(0)
...@@ -141,6 +142,7 @@ function startGameCountdown(seconds = 60) { ...@@ -141,6 +142,7 @@ function startGameCountdown(seconds = 60) {
countdownInterval.value = 0 countdownInterval.value = 0
gameCountdownTimer = undefined gameCountdownTimer = undefined
setDivDescVisible(false) setDivDescVisible(false)
isGameEnded.value = true
hasFinalScoreResult.value = false hasFinalScoreResult.value = false
submitScore(true) submitScore(true)
if (userTop10RankStatus.value) { if (userTop10RankStatus.value) {
...@@ -192,6 +194,7 @@ function startGameView() { ...@@ -192,6 +194,7 @@ function startGameView() {
currentGuFrame.value = 0 currentGuFrame.value = 0
roomStatus.value = 2 roomStatus.value = 2
hasFinalScoreResult.value = false hasFinalScoreResult.value = false
isGameEnded.value = false
currentView.value = 'playing' currentView.value = 'playing'
startGameCountdown() startGameCountdown()
} }
...@@ -298,6 +301,7 @@ if (wechat) { ...@@ -298,6 +301,7 @@ if (wechat) {
showGameRule.value = false showGameRule.value = false
// showGameRank.value = false // showGameRank.value = false
roomStatus.value = 2 roomStatus.value = 2
isGameEnded.value = false
hasFinalScoreResult.value = false hasFinalScoreResult.value = false
currentView.value = 'playing' currentView.value = 'playing'
startGameCountdown( startGameCountdown(
...@@ -363,7 +367,7 @@ const showGameRuleHandler = () => { ...@@ -363,7 +367,7 @@ const showGameRuleHandler = () => {
@touchGameRule="showGameRuleHandler" /> @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-frame="currentGuFrame" :countdown-interval="countdownInterval" :current-gu-frame="currentGuFrame" :countdown-interval="countdownInterval"
:is-div-desc-visible="isDivDescVisible" @touch="touchHandler" :userTop10RankStatus="userTop10RankStatus" /> :is-div-desc-visible="isDivDescVisible" :is-game-ended="isGameEnded" @touch="touchHandler" :userTop10RankStatus="userTop10RankStatus" />
<ScoreView v-else :image-urls="imageUrls" :rank="rank" :tick="tick" /> <ScoreView v-else :image-urls="imageUrls" :rank="rank" :tick="tick" />
</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;">
......
<script setup lang="ts"> <script setup lang="ts">
defineProps<{ const props = defineProps<{
imageUrls: Record<string, string> imageUrls: Record<string, string>
countdownInterval: number countdownInterval: number
isDivDescVisible: boolean isDivDescVisible: boolean
isGameEnded?: boolean
tick: number tick: number
rank: number rank: number
currentGuFrame: number, currentGuFrame: number,
userTop10RankStatus: boolean, userTop10RankStatus: boolean,
}>() }>()
defineEmits<{ const emit = defineEmits<{
touch: [] touch: []
}>() }>()
function handleTouch() {
if (props.isGameEnded) return
emit('touch')
}
</script> </script>
<template> <template>
...@@ -29,7 +35,7 @@ defineEmits<{ ...@@ -29,7 +35,7 @@ defineEmits<{
<!-- <div v-if="!userTop10RankStatus">当前排名: &nbsp;&nbsp;<label></label>&nbsp;</div> --> <!-- <div v-if="!userTop10RankStatus">当前排名: &nbsp;&nbsp;<label></label>&nbsp;</div> -->
</div> </div>
<div class="bg-bottom"></div> <div class="bg-bottom"></div>
<div class="play-gu" :style="{ backgroundPosition: `-${currentGuFrame * 400}px 0` }" @click="$emit('touch')"></div> <div class="play-gu" :style="{ backgroundPosition: `-${currentGuFrame * 400}px 0` }" @click="handleTouch"></div>
</div> </div>
</template> </template>
......
...@@ -5,10 +5,11 @@ import MobileStage from '@/components/MobileStage.vue' ...@@ -5,10 +5,11 @@ import MobileStage from '@/components/MobileStage.vue'
import { useGameSocket, sendGameMessage, userJoinStatus, userTop10RankStatus, joinSharedRoom } from '@/composables/useGameSocket' import { useGameSocket, sendGameMessage, userJoinStatus, userTop10RankStatus, joinSharedRoom } 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 ScoreView from './views/ScoreView.vue'
import { $format_str, $getWechat, $toast } from '@/commons/utils.ts' import { $format_str, $getWechat, $toast } from '@/commons/utils.ts'
import { playGame2Music, stopAllMusic } from '@/commons/music'; import { playGame2Music, stopAllMusic } from '@/commons/music';
type GameView = 'loading' | 'playing' type GameView = 'loading' | 'playing' | 'score'
type RankPlayer = { type RankPlayer = {
rank: number rank: number
nickname: string nickname: string
...@@ -17,6 +18,8 @@ type RankPlayer = { ...@@ -17,6 +18,8 @@ type RankPlayer = {
} }
const imageUrls: Record<string, string> = { const imageUrls: Record<string, string> = {
avatar: cssAssetUrl('avatar-yellow.png'),
scoreBg: cssAssetUrl('game1/score-bg.png'),
bg: cssAssetUrl('game2/bg.png'), bg: cssAssetUrl('game2/bg.png'),
logo: cssAssetUrl('logo.png'), logo: cssAssetUrl('logo.png'),
close: cssAssetUrl('game1/close.png'), close: cssAssetUrl('game1/close.png'),
...@@ -35,6 +38,7 @@ const wechat = $getWechat() ...@@ -35,6 +38,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 isGameEnded = ref(false)
const score = ref(0) const score = ref(0)
const rank = ref(0) //排名 const rank = ref(0) //排名
const roomStatus = ref(0) const roomStatus = ref(0)
...@@ -174,8 +178,8 @@ function startGameCountdown(seconds = 60) { ...@@ -174,8 +178,8 @@ function startGameCountdown(seconds = 60) {
if (countdownInterval.value <= 0) { if (countdownInterval.value <= 0) {
countdownInterval.value = 0 countdownInterval.value = 0
gameCountdownTimer = undefined gameCountdownTimer = undefined
currentView.value = 'loading'
setDivDescVisible(false) setDivDescVisible(false)
isGameEnded.value = true
hasFinalScoreResult.value = false hasFinalScoreResult.value = false
submitScore(true) submitScore(true)
if (userTop10RankStatus.value) { if (userTop10RankStatus.value) {
...@@ -242,6 +246,7 @@ function startGameView() { ...@@ -242,6 +246,7 @@ function startGameView() {
showGameRank.value = false showGameRank.value = false
roomStatus.value = 2 roomStatus.value = 2
hasFinalScoreResult.value = false hasFinalScoreResult.value = false
isGameEnded.value = false
currentView.value = 'playing' currentView.value = 'playing'
startGameCountdown() startGameCountdown()
} }
...@@ -249,8 +254,8 @@ function startGameView() { ...@@ -249,8 +254,8 @@ function startGameView() {
function showGameOverRank() { function showGameOverRank() {
stopGameCountdown() stopGameCountdown()
setDivDescVisible(false) setDivDescVisible(false)
currentView.value = 'loading' currentView.value = 'score'
showGameRank.value = true showGameRank.value = false
userJoinStatus.value = false; userJoinStatus.value = false;
} }
...@@ -276,7 +281,7 @@ if (wechat) { ...@@ -276,7 +281,7 @@ if (wechat) {
//第一个游戏没有排行榜,只显示结果 //第一个游戏没有排行榜,只显示结果
showScoreView(); showScoreView();
rankList.value = data; rankList.value = data;
showGameRank.value = true; showGameRank.value = false;
}, },
onGameStart: async () => { onGameStart: async () => {
showGameRule.value = false; showGameRule.value = false;
...@@ -329,6 +334,7 @@ if (wechat) { ...@@ -329,6 +334,7 @@ if (wechat) {
showGameRule.value = false showGameRule.value = false
// showGameRank.value = false // showGameRank.value = false
roomStatus.value = 2 roomStatus.value = 2
isGameEnded.value = false
hasFinalScoreResult.value = false hasFinalScoreResult.value = false
currentView.value = 'playing' currentView.value = 'playing'
startGameCountdown( startGameCountdown(
...@@ -352,7 +358,7 @@ function showScoreView() { ...@@ -352,7 +358,7 @@ function showScoreView() {
showGameRule.value = false; showGameRule.value = false;
stopGameCountdown() stopGameCountdown()
setDivDescVisible(false) setDivDescVisible(false)
currentView.value = 'loading' currentView.value = 'score'
} }
onMounted(() => { onMounted(() => {
...@@ -444,8 +450,9 @@ const rankCloseHandler = () => { ...@@ -444,8 +450,9 @@ const rankCloseHandler = () => {
</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-if="currentView === 'playing'" :image-urls="imageUrls" :tick="score" :rank="rank" :countdown-interval="countdownInterval"
:is-div-desc-visible="isDivDescVisible" @touch="touchHandler" /> :is-div-desc-visible="isDivDescVisible" :is-game-ended="isGameEnded" @touch="touchHandler" />
<ScoreView v-else :image-urls="imageUrls" :tick="score" :rank="rank" />
</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;">
请使用微信扫码进入游戏 请使用微信扫码进入游戏
......
<script setup lang="ts"> <script setup lang="ts">
import { onBeforeUnmount, ref } from 'vue'; import { onBeforeUnmount, ref, watch } from 'vue';
import { isGameSocketConnected } from '@/composables/useGameSocket'; import { isGameSocketConnected } from '@/composables/useGameSocket';
defineProps<{ const props = defineProps<{
imageUrls: Record<string, string> imageUrls: Record<string, string>
countdownInterval: number countdownInterval: number
isDivDescVisible: boolean isDivDescVisible: boolean
isGameEnded?: boolean
tick: number tick: number
rank: number, rank: number,
// currentGu: string // currentGu: string
...@@ -46,6 +47,7 @@ function normalizeAngle(angle: number) { ...@@ -46,6 +47,7 @@ function normalizeAngle(angle: number) {
} }
function startRotation(event: PointerEvent) { function startRotation(event: PointerEvent) {
if (props.isGameEnded) return
if (activePointerId !== null) return if (activePointerId !== null) return
stopInertia() stopInertia()
...@@ -57,6 +59,7 @@ function startRotation(event: PointerEvent) { ...@@ -57,6 +59,7 @@ function startRotation(event: PointerEvent) {
} }
function rotateCoin(event: PointerEvent) { function rotateCoin(event: PointerEvent) {
if (props.isGameEnded) return
if (event.pointerId !== activePointerId) return if (event.pointerId !== activePointerId) return
const currentAngle = getPointerAngle(event) const currentAngle = getPointerAngle(event)
...@@ -122,6 +125,14 @@ function startInertia() { ...@@ -122,6 +125,14 @@ function startInertia() {
} }
onBeforeUnmount(stopInertia) onBeforeUnmount(stopInertia)
watch(() => props.isGameEnded, (isEnded) => {
if (!isEnded) return
activePointerId = null
clockwiseAngle = 0
angularVelocity = 0
stopInertia()
})
</script> </script>
<template> <template>
......
...@@ -5,10 +5,11 @@ import MobileStage from '@/components/MobileStage.vue' ...@@ -5,10 +5,11 @@ import MobileStage from '@/components/MobileStage.vue'
import { useGameSocket, joinSharedRoom, sendGameMessage, userJoinStatus, userTop10RankStatus } from '@/composables/useGameSocket' import { useGameSocket, joinSharedRoom, sendGameMessage, userJoinStatus, userTop10RankStatus } 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 ScoreView from './views/ScoreView.vue'
import { $getWechat, $toast, $is_run_local } from '@/commons/utils.ts' import { $getWechat, $toast, $is_run_local } from '@/commons/utils.ts'
import { playGame3Music, stopAllMusic } from '@/commons/music'; import { playGame3Music, stopAllMusic } from '@/commons/music';
type GameView = 'loading' | 'playing' type GameView = 'loading' | 'playing' | 'score'
type RankPlayer = { type RankPlayer = {
rank: number rank: number
nickname: string nickname: string
...@@ -17,6 +18,8 @@ type RankPlayer = { ...@@ -17,6 +18,8 @@ type RankPlayer = {
} }
const imageUrls: Record<string, string> = { const imageUrls: Record<string, string> = {
avatar: cssAssetUrl('avatar-yellow.png'),
scoreBg: cssAssetUrl('game1/score-bg.png'),
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'), left: cssAssetUrl('game3/icon_zuo.webp'),
...@@ -192,7 +195,6 @@ function startGameCountdown(seconds = 60) { ...@@ -192,7 +195,6 @@ function startGameCountdown(seconds = 60) {
if (countdownInterval.value <= 0) { if (countdownInterval.value <= 0) {
countdownInterval.value = 0 countdownInterval.value = 0
gameCountdownTimer = undefined gameCountdownTimer = undefined
currentView.value = 'loading'
setDivDescVisible(false) setDivDescVisible(false)
hasFinalScoreResult.value = false hasFinalScoreResult.value = false
submitScore(true) submitScore(true)
...@@ -266,8 +268,8 @@ function startGameView() { ...@@ -266,8 +268,8 @@ function startGameView() {
function showGameOverRank() { function showGameOverRank() {
stopGameCountdown() stopGameCountdown()
setDivDescVisible(false) setDivDescVisible(false)
currentView.value = 'loading' currentView.value = 'score'
showGameRank.value = true showGameRank.value = false
userJoinStatus.value = false userJoinStatus.value = false
if (isLocalMode && !wechat) { if (isLocalMode && !wechat) {
console.log('[game3 本地模式] 游戏结束,最终分数:', score.value) console.log('[game3 本地模式] 游戏结束,最终分数:', score.value)
...@@ -477,8 +479,9 @@ const rankCloseHandler = () => { ...@@ -477,8 +479,9 @@ const rankCloseHandler = () => {
</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-if="currentView === 'playing'" :image-urls="imageUrls" :tick="score" :rank="rank" :countdown-interval="countdownInterval"
:is-div-desc-visible="isDivDescVisible" @touch="touchHandler" @score-change="scoreChangeHandler" :userTop10RankStatus="userTop10RankStatus" /> :is-div-desc-visible="isDivDescVisible" @touch="touchHandler" @score-change="scoreChangeHandler" :userTop10RankStatus="userTop10RankStatus" />
<ScoreView v-else :image-urls="imageUrls" :tick="score" :rank="rank" />
</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;">
请使用微信扫码进入游戏 请使用微信扫码进入游戏
......
<!-- <script setup lang="ts"> <script setup lang="ts">
import { $getWechat } from '@/commons/utils'; import { $getWechat } from '@/commons/utils';
import { onMounted, ref } from 'vue'; import { onMounted, ref } from 'vue';
...@@ -9,12 +9,13 @@ defineProps<{ ...@@ -9,12 +9,13 @@ defineProps<{
}>() }>()
defineEmits<{ defineEmits<{
showRank: []
replay: [] replay: []
back: [] back: []
}>() }>()
const nickname = ref(''); const nickname = ref('');
const avatar = ref(''); const avatar = ref('');
onMounted(() => { onMounted(() => {
const wechat = $getWechat(); const wechat = $getWechat();
nickname.value = wechat.nickname; nickname.value = wechat.nickname;
...@@ -25,6 +26,19 @@ onMounted(() => { ...@@ -25,6 +26,19 @@ onMounted(() => {
<template> <template>
<div class="h5-page game-stage"> <div class="h5-page game-stage">
<div class="img-logo"></div> <div class="img-logo"></div>
<div class="bg-bottom"></div>
<div class="score-card">
<div class="score-avatar" :style="{ backgroundImage: `url(${avatar})` }"></div>
<div class="score-content">
<div>{{ nickname }}</div>
<div>您的成绩</div>
<div>当前积分</div>
<div>{{ tick }}</div>
<div>最终排名</div>
<div v-if="rank>0"><label>{{ rank }}</label></div>
<div v-else>未上榜</div>
</div>
</div>
</div> </div>
</template> </template>
...@@ -36,6 +50,16 @@ onMounted(() => { ...@@ -36,6 +50,16 @@ onMounted(() => {
padding: 0; padding: 0;
} }
.bg-bottom {
position: absolute;
bottom: 0;
left: var(--stage-viewport-left, 0);
width: var(--stage-viewport-width, 750px);
height: 479px;
background: v-bind('imageUrls.bg2') center/cover;
opacity: 0.6;
}
.img-logo { .img-logo {
position: absolute; position: absolute;
top: 66px; top: 66px;
...@@ -46,4 +70,61 @@ onMounted(() => { ...@@ -46,4 +70,61 @@ onMounted(() => {
transform: translateX(-50%); transform: translateX(-50%);
} }
</style> --> .score-card {
position: absolute;
top: 450px;
left: 50%;
width: 465px;
height: 620px;
border-radius: 24px;
background: rgba(255, 255, 255, 0.92);
transform: translateX(-50%) scale(1.2);
}
.score-avatar {
position: absolute;
top: -50px;
left: 50%;
width: 132px;
height: 132px;
border-radius: 66px;
background: center/cover;
transform: translateX(-50%);
}
.score-content {
position: absolute;
bottom: 0;
left: 0;
width: 100%;
height: calc(100% - 100px);
font-size: 28pt;
text-align: center;
}
.score-content>div:nth-child(1) {
color: #E00000;
font-size: 32pt;
font-weight: bold;
}
.score-content>div:nth-child(2) {
margin-top: 20px;
font-size: 32pt;
}
.score-content>div:nth-child(3) {
margin-top: 40px;
}
.score-content>div:nth-child(4) {
margin-top: 30px;
color: #E00000;
font-size: 32pt;
transform: scale(1.5);
}
.score-content>div:nth-child(5) {
margin-top: 40px;
}
</style>
...@@ -57,6 +57,7 @@ const stageBackground = computed(() => { ...@@ -57,6 +57,7 @@ const stageBackground = computed(() => {
}); });
const countdownInterval = ref(60); const countdownInterval = ref(60);
const isDivDescVisible = ref(false); const isDivDescVisible = ref(false);
const isGameEnded = ref(false);
const tick = ref(0); // 点击次数/摇动次数 const tick = ref(0); // 点击次数/摇动次数
const rank = ref(0); // 排名 const rank = ref(0); // 排名
const roomStatus = ref(0) const roomStatus = ref(0)
...@@ -161,6 +162,7 @@ function startGameCountdown(seconds = 60) { ...@@ -161,6 +162,7 @@ function startGameCountdown(seconds = 60) {
countdownInterval.value = 0; countdownInterval.value = 0;
gameCountdownTimer = undefined; gameCountdownTimer = undefined;
setDivDescVisible(false); setDivDescVisible(false);
isGameEnded.value = true;
submitScore(true); submitScore(true);
if (userTop10RankStatus.value) { if (userTop10RankStatus.value) {
userJoinStatus.value = false; userJoinStatus.value = false;
...@@ -214,6 +216,7 @@ function startGameView() { ...@@ -214,6 +216,7 @@ function startGameView() {
stopGameCountdown(); stopGameCountdown();
tick.value = 0; tick.value = 0;
currentHorse.value = imageUrls.horse; currentHorse.value = imageUrls.horse;
isGameEnded.value = false;
currentView.value = "playing"; currentView.value = "playing";
startGameCountdown(60); startGameCountdown(60);
} }
...@@ -361,7 +364,7 @@ onBeforeUnmount(() => { ...@@ -361,7 +364,7 @@ onBeforeUnmount(() => {
<!-- <PlayingView v-else :image-urls="imageUrls" :tick="tick" :rank="rank" --> <!-- <PlayingView v-else :image-urls="imageUrls" :tick="tick" :rank="rank" -->
<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"
:currentHorse="currentHorse" :currentYaoyiyao="currentYaoyiyao" :countdown-interval="countdownInterval" :currentHorse="currentHorse" :currentYaoyiyao="currentYaoyiyao" :countdown-interval="countdownInterval"
:is-div-desc-visible="isDivDescVisible" @touch="touchHandler" :is-div-desc-visible="isDivDescVisible" :is-game-ended="isGameEnded" @touch="touchHandler"
:userTop10RankStatus="userTop10RankStatus" /> :userTop10RankStatus="userTop10RankStatus" />
<ScoreView v-else :image-urls="imageUrls" :tick="tick" :level="rank" @replay="replayGame" @back="backToWaiting" /> <ScoreView v-else :image-urls="imageUrls" :tick="tick" :level="rank" @replay="replayGame" @back="backToWaiting" />
</MobileStage> </MobileStage>
......
<script setup lang="ts"> <script setup lang="ts">
import { onBeforeUnmount, onMounted, ref } from 'vue' import { onBeforeUnmount, onMounted, ref, watch } from 'vue'
import { assetUrl } from '@/commons/assets' import { assetUrl } from '@/commons/assets'
const shakeSound = assetUrl('game4/yaoyiyao.mp3') const shakeSound = assetUrl('game4/yaoyiyao.mp3')
...@@ -13,6 +13,7 @@ const props = defineProps<{ ...@@ -13,6 +13,7 @@ const props = defineProps<{
rank: number rank: number
currentHorse: string currentHorse: string
currentYaoyiyao: string, currentYaoyiyao: string,
isGameEnded?: boolean
userTop10RankStatus: boolean userTop10RankStatus: boolean
}>() }>()
...@@ -125,6 +126,7 @@ const playShakeSound = () => { ...@@ -125,6 +126,7 @@ const playShakeSound = () => {
} }
const handleDeviceMotion = (ev: DeviceMotionEvent) => { const handleDeviceMotion = (ev: DeviceMotionEvent) => {
if (props.isGameEnded) return
const nowTime = Date.now() const nowTime = Date.now()
const motion = ev.accelerationIncludingGravity const motion = ev.accelerationIncludingGravity
if (!motion || motion.x === null) return if (!motion || motion.x === null) return
...@@ -213,12 +215,22 @@ onBeforeUnmount(() => { ...@@ -213,12 +215,22 @@ onBeforeUnmount(() => {
// 点击马触发:iOS 先请求权限(不触发得分) // 点击马触发:iOS 先请求权限(不触发得分)
const onTapHorse = async () => { const onTapHorse = async () => {
if (props.isGameEnded) return
if (!motionPermissionGranted) { if (!motionPermissionGranted) {
await requestMotionPermission() await requestMotionPermission()
showIOSHint.value = false showIOSHint.value = false
} }
} }
watch(() => props.isGameEnded, (isEnded) => {
if (!isEnded) return
isYaoyiyaoShaking.value = false
if (yaoyiyaoShakeTimer) {
clearTimeout(yaoyiyaoShakeTimer)
yaoyiyaoShakeTimer = null
}
})
</script> </script>
<template> <template>
......
...@@ -297,8 +297,8 @@ function startGameView() { ...@@ -297,8 +297,8 @@ function startGameView() {
function showGameOverRank() { function showGameOverRank() {
stopGameCountdown() stopGameCountdown()
setDivDescVisible(false) setDivDescVisible(false)
currentView.value = 'loading' currentView.value = 'score'
showGameRank.value = true showGameRank.value = false
} }
...@@ -465,7 +465,7 @@ const rankCloseHandler = () => { ...@@ -465,7 +465,7 @@ const rankCloseHandler = () => {
<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"
@hit="hitHandler" /> @hit="hitHandler" />
<!-- <ScoreView v-else :image-urls="imageUrls" :rank="rank" :tick="tick" /> --> <ScoreView v-else :image-urls="imageUrls" :rank="rank" :tick="tick" />
</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;">
请使用微信扫码进入游戏 请使用微信扫码进入游戏
......
...@@ -5,10 +5,11 @@ import MobileStage from '@/components/MobileStage.vue' ...@@ -5,10 +5,11 @@ import MobileStage from '@/components/MobileStage.vue'
import { useGameSocket, sendGameMessage, userJoinStatus, userTop10RankStatus, joinSharedRoom } from '@/composables/useGameSocket' import { useGameSocket, sendGameMessage, userJoinStatus, userTop10RankStatus, joinSharedRoom } 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 ScoreView from './views/ScoreView.vue'
import { $format_str, $getWechat, $toast } from '@/commons/utils.ts' import { $format_str, $getWechat, $toast } from '@/commons/utils.ts'
import { playGame6Music, stopAllMusic } from '@/commons/music'; import { playGame6Music, stopAllMusic } from '@/commons/music';
type GameView = 'loading' | 'playing' type GameView = 'loading' | 'playing' | 'score'
type RankPlayer = { type RankPlayer = {
rank: number rank: number
nickname: string nickname: string
...@@ -17,6 +18,8 @@ type RankPlayer = { ...@@ -17,6 +18,8 @@ type RankPlayer = {
} }
const imageUrls: Record<string, string> = { const imageUrls: Record<string, string> = {
avatar: cssAssetUrl('avatar-yellow.png'),
scoreBg: cssAssetUrl('game1/score-bg.png'),
bg: cssAssetUrl('game6/bg.png'), bg: cssAssetUrl('game6/bg.png'),
logo: cssAssetUrl('logo.png'), logo: cssAssetUrl('logo.png'),
loadingBg1: cssAssetUrl('game6/loadingbg1.png'), loadingBg1: cssAssetUrl('game6/loadingbg1.png'),
...@@ -42,6 +45,7 @@ const wechat = $getWechat() ...@@ -42,6 +45,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 isGameEnded = ref(false)
const score = ref(0) const score = ref(0)
const rank = ref(0) //排名 const rank = ref(0) //排名
const roomStatus = ref(0) const roomStatus = ref(0)
...@@ -181,8 +185,8 @@ function startGameCountdown(seconds = 60) { ...@@ -181,8 +185,8 @@ function startGameCountdown(seconds = 60) {
if (countdownInterval.value <= 0) { if (countdownInterval.value <= 0) {
countdownInterval.value = 0 countdownInterval.value = 0
gameCountdownTimer = undefined gameCountdownTimer = undefined
currentView.value = 'loading'
setDivDescVisible(false) setDivDescVisible(false)
isGameEnded.value = true
hasFinalScoreResult.value = false hasFinalScoreResult.value = false
submitScore(true) submitScore(true)
if (userTop10RankStatus.value) { if (userTop10RankStatus.value) {
...@@ -248,6 +252,7 @@ function startGameView() { ...@@ -248,6 +252,7 @@ function startGameView() {
showGameRank.value = false showGameRank.value = false
roomStatus.value = 2 roomStatus.value = 2
hasFinalScoreResult.value = false hasFinalScoreResult.value = false
isGameEnded.value = false
currentView.value = 'playing' currentView.value = 'playing'
startGameCountdown() startGameCountdown()
} }
...@@ -255,8 +260,8 @@ function startGameView() { ...@@ -255,8 +260,8 @@ function startGameView() {
function showGameOverRank() { function showGameOverRank() {
stopGameCountdown() stopGameCountdown()
setDivDescVisible(false) setDivDescVisible(false)
currentView.value = 'loading' currentView.value = 'score'
showGameRank.value = true showGameRank.value = false
userJoinStatus.value = false; userJoinStatus.value = false;
} }
...@@ -335,6 +340,7 @@ if (wechat) { ...@@ -335,6 +340,7 @@ if (wechat) {
showGameRule.value = false showGameRule.value = false
showGameRank.value = false showGameRank.value = false
roomStatus.value = 2 roomStatus.value = 2
isGameEnded.value = false
hasFinalScoreResult.value = false hasFinalScoreResult.value = false
currentView.value = 'playing' currentView.value = 'playing'
startGameCountdown( startGameCountdown(
...@@ -442,8 +448,9 @@ const rankCloseHandler = () => { ...@@ -442,8 +448,9 @@ const rankCloseHandler = () => {
</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-if="currentView === 'playing'" :image-urls="imageUrls" :tick="score" :rank="rank" :countdown-interval="countdownInterval"
:is-div-desc-visible="isDivDescVisible" @touch="touchHandler" /> :is-div-desc-visible="isDivDescVisible" :is-game-ended="isGameEnded" @touch="touchHandler" />
<ScoreView v-else :image-urls="imageUrls" :tick="score" :rank="rank" />
</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;">
请使用微信扫码进入游戏 请使用微信扫码进入游戏
......
<script setup lang="ts"> <script setup lang="ts">
import { onBeforeUnmount, onMounted, ref } from 'vue'; import { onBeforeUnmount, onMounted, ref, watch } from 'vue';
defineProps<{ const props = defineProps<{
imageUrls: Record<string, string> imageUrls: Record<string, string>
countdownInterval: number countdownInterval: number
isDivDescVisible: boolean isDivDescVisible: boolean
isGameEnded?: boolean
tick: number tick: number
rank: number rank: number
}>() }>()
...@@ -41,6 +42,13 @@ for (let i = 0; i < 9; i++) { ...@@ -41,6 +42,13 @@ for (let i = 0; i < 9; i++) {
let spawnTimer: ReturnType<typeof window.setTimeout> | undefined let spawnTimer: ReturnType<typeof window.setTimeout> | undefined
function clearSpawnTimer() {
if (spawnTimer) {
window.clearTimeout(spawnTimer)
spawnTimer = undefined
}
}
function clearTargetTimer(item: TargetItem) { function clearTargetTimer(item: TargetItem) {
if (item.timer) { if (item.timer) {
window.clearTimeout(item.timer) window.clearTimeout(item.timer)
...@@ -110,6 +118,9 @@ function spawnRandomTargets(duration = 1000) { ...@@ -110,6 +118,9 @@ function spawnRandomTargets(duration = 1000) {
} }
function scheduleRandomTargets() { function scheduleRandomTargets() {
if (props.isGameEnded) {
return
}
spawnRandomTargets(1000) spawnRandomTargets(1000)
spawnTimer = window.setTimeout(scheduleRandomTargets, 1200) spawnTimer = window.setTimeout(scheduleRandomTargets, 1200)
} }
...@@ -170,11 +181,21 @@ onMounted(() => { ...@@ -170,11 +181,21 @@ onMounted(() => {
scheduleRandomTargets() scheduleRandomTargets()
}) })
onBeforeUnmount(() => { watch(() => props.isGameEnded, (isEnded) => {
if (spawnTimer) { if (!isEnded) {
window.clearTimeout(spawnTimer) scheduleRandomTargets()
return
} }
clearSpawnTimer()
for (const item of list.value) {
resetTarget(item.id)
}
})
onBeforeUnmount(() => {
clearSpawnTimer()
for (const item of list.value) { for (const item of list.value) {
clearTargetTimer(item) clearTargetTimer(item)
} }
......
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