Commit c6bf1726 authored by 陈冲's avatar 陈冲

修复

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