From e116c8d22f5ec7c5b3e2d542ca57a06a151f2a44 Mon Sep 17 00:00:00 2001 From: kron Date: Mon, 28 Jul 2025 13:54:37 +0800 Subject: [PATCH] =?UTF-8?q?=E6=AF=94=E8=B5=9B=E9=80=BB=E8=BE=91=E4=BB=A3?= =?UTF-8?q?=E7=A0=81=E7=BB=9F=E4=B8=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/ShootProgress.vue | 25 +- src/pages.json | 3 + src/pages/battle-room.vue | 519 ++----------------------------- src/pages/match-page.vue | 98 ++++++ src/pages/melee-match.vue | 153 ++++----- src/pages/ranking.vue | 27 +- src/pages/team-match.vue | 200 +++++------- src/websocket.js | 29 +- 8 files changed, 290 insertions(+), 764 deletions(-) create mode 100644 src/pages/match-page.vue diff --git a/src/components/ShootProgress.vue b/src/components/ShootProgress.vue index 8324d7d..b7c8845 100644 --- a/src/components/ShootProgress.vue +++ b/src/components/ShootProgress.vue @@ -23,10 +23,6 @@ const props = defineProps({ type: Number, default: 120, }, - seq: { - type: Number, - default: 0, - }, currentRound: { type: Number, default: 0, @@ -47,7 +43,7 @@ const timer = ref(null); const sound = ref(true); const currentSound = ref(""); const currentRound = ref(props.currentRound); -const currentRoundEnded = ref(!props.battleId); +const currentRoundEnded = ref(false); const ended = ref(false); const halfTime = ref(false); @@ -79,26 +75,21 @@ watch( watch( () => props.tips, (newVal) => { - let key = ""; if (newVal.includes("红队")) barColor.value = "#FF6060"; if (newVal.includes("蓝队")) barColor.value = "#5FADFF"; + if (newVal.includes("红队") || newVal.includes("蓝队")) { + if (timer.value) clearInterval(timer.value); + remain.value = props.total; + timer.value = setInterval(() => { + if (remain.value > 0) remain.value--; + }, 1000); + } }, { immediate: true, } ); -watch( - () => [props.seq], - () => { - if (timer.value) clearInterval(timer.value); - remain.value = props.total; - timer.value = setInterval(() => { - if (remain.value > 0) remain.value--; - }, 1000); - } -); - watch( () => props.start, (newVal) => { diff --git a/src/pages.json b/src/pages.json index c74c55f..ce08b29 100644 --- a/src/pages.json +++ b/src/pages.json @@ -3,6 +3,9 @@ { "path": "pages/index" }, + { + "path": "pages/match-page" + }, { "path": "pages/image-share" }, diff --git a/src/pages/battle-room.vue b/src/pages/battle-room.vue index ff9e8cb..809725a 100644 --- a/src/pages/battle-room.vue +++ b/src/pages/battle-room.vue @@ -4,222 +4,23 @@ import { onLoad, onShow, onHide } from "@dcloudio/uni-app"; import Container from "@/components/Container.vue"; import PlayerSeats from "@/components/PlayerSeats.vue"; import Guide from "@/components/Guide.vue"; -import Timer from "@/components/Timer.vue"; import SButton from "@/components/SButton.vue"; -import BowTarget from "@/components/BowTarget.vue"; -import BattleHeader from "@/components/BattleHeader.vue"; -import BattleFooter from "@/components/BattleFooter.vue"; -import BowPower from "@/components/BowPower.vue"; -import ShootProgress from "@/components/ShootProgress.vue"; -import PlayersRow from "@/components/PlayersRow.vue"; import SModal from "@/components/SModal.vue"; -import ScreenHint from "@/components/ScreenHint.vue"; -import RoundEndTip from "@/components/RoundEndTip.vue"; -import TestDistance from "@/components/TestDistance.vue"; -import PlayerScore from "@/components/PlayerScore.vue"; -import Avatar from "@/components/Avatar.vue"; -import { - getRoomAPI, - destroyRoomAPI, - exitRoomAPI, - startRoomAPI, - getCurrentGameAPI, -} from "@/apis"; -import { isGameEnded } from "@/util"; -import { MESSAGETYPES, roundsName, getMessageTypeName } from "@/constants"; +import { getRoomAPI, destroyRoomAPI, exitRoomAPI, startRoomAPI } from "@/apis"; +import { MESSAGETYPES } from "@/constants"; import useStore from "@/store"; import { storeToRefs } from "pinia"; const store = useStore(); const { user } = storeToRefs(store); -const step = ref(1); -const seq = ref(0); -const battleId = ref(""); const room = ref({}); const roomNumber = ref(""); const owner = ref({}); const opponent = ref({}); -const redTeam = ref([]); -const blueTeam = ref([]); -const currentShooterId = ref(0); const players = ref([]); -const playersSorted = ref([]); -const currentRound = ref(1); -const totalRounds = ref(0); -const start = ref(false); -const startCount = ref(true); -const power = ref(0); -const scores = ref([]); -const blueScores = ref([]); -const tips = ref("即将开始..."); -const roundResults = ref([]); -const redPoints = ref(0); -const bluePoints = ref(0); -const currentRedPoint = ref(0); -const currentBluePoint = ref(0); -const showRoundTip = ref(false); -const playersScores = ref({}); + const showModal = ref(false); -const halfTimeTip = ref(false); -const isFinalShoot = ref(false); -const total = ref(15); const battleType = ref(0); -const isEnded = ref(false); const refreshRoomTimer = ref(null); -const refreshTimer = ref(null); - -watch( - () => [players.value, playersScores.value], - ([n_players, n_scores]) => { - if (n_players.length) { - playersSorted.value = Object.keys(n_scores) - .sort((a, b) => n_scores[b].length - n_scores[a].length) - .map((pid) => n_players.find((p) => p.id == pid)); - } - }, - { - deep: true, // 添加深度监听 - immediate: true, - } -); - -function recoverData(battleInfo) { - uni.removeStorageSync("last-awake-time"); - battleId.value = battleInfo.id; - battleType.value = battleInfo.config.mode; - step.value = 2; - if (battleInfo.status === 0) { - const readyRemain = Date.now() / 1000 - battleInfo.startTime; - console.log(`当前局已进行${readyRemain}秒`); - if (readyRemain > 0) { - setTimeout(() => { - uni.$emit("update-timer", 15 - readyRemain); - }, 200); - } - return; - } else { - step.value = 3; - start.value = true; - } - if (battleInfo.config.mode === 1) { - redTeam.value = battleInfo.redTeam; - blueTeam.value = battleInfo.blueTeam; - if (battleInfo.status !== 0) { - bluePoints.value = 0; - redPoints.value = 0; - currentRound.value = battleInfo.currentRound; - totalRounds.value = battleInfo.maxRound; - roundResults.value = battleInfo.roundResults; - battleInfo.roundResults.forEach((round) => { - const blueTotal = round.blueArrows.reduce( - (last, next) => last + next.ring, - 0 - ); - const redTotal = round.redArrows.reduce( - (last, next) => last + next.ring, - 0 - ); - if (blueTotal === redTotal) { - bluePoints.value += 1; - redPoints.value += 1; - } else if (blueTotal > redTotal) { - bluePoints.value += 2; - } else { - redPoints.value += 2; - } - }); - if ( - battleInfo.redTeam[0].shotHistory[battleInfo.currentRound] || - battleInfo.blueTeam[0].shotHistory[battleInfo.currentRound] - ) { - roundResults.value.push({ - redArrows: battleInfo.redTeam[0].shotHistory[ - battleInfo.currentRound - ].filter((item) => !!item.playerId), - blueArrows: battleInfo.blueTeam[0].shotHistory[ - battleInfo.currentRound - ].filter((item) => !!item.playerId), - }); - } else if (battleInfo.currentRound < 5) { - roundResults.value.push({ - redArrows: [], - blueArrows: [], - }); - } - if (battleInfo.goldenRound) { - const { ShotCount, RedRecords, BlueRecords } = battleInfo.goldenRound; - const roundCount = Math.max(RedRecords.length, BlueRecords.length); - currentRound.value += roundCount; - isFinalShoot.value = true; - for (let i = 0; i < roundCount; i++) { - const roundData = { - redArrows: - RedRecords && RedRecords[i] ? RedRecords[i].Arrows || [] : [], - blueArrows: - BlueRecords && BlueRecords[i] ? BlueRecords[i].Arrows || [] : [], - }; - if (roundResults.value[5 + i]) { - roundResults.value[5 + i] = roundData; - } else { - roundResults.value.push(roundData); - } - } - } - const lastIndex = roundResults.value.length - 1; - if (roundResults.value[lastIndex]) { - const redArrows = roundResults.value[lastIndex].redArrows; - scores.value = [...redArrows].filter((item) => !!item.playerId); - const blueArrows = roundResults.value[lastIndex].blueArrows; - blueScores.value = [...blueArrows].filter((item) => !!item.playerId); - } - } - // 这个状态不准 - // if (battleInfo.status !== 11) return; - if (battleInfo.firePlayerIndex) { - currentShooterId.value = battleInfo.firePlayerIndex; - tips.value = - redTeam.value[0].id === currentShooterId.value - ? "请红队射箭 - " - : "请蓝队射箭 - "; - tips.value += isFinalShoot.value - ? "决金箭" - : `第${roundsName[currentRound.value]}轮`; - } - if (battleInfo.fireTime > 0) { - const remain = Date.now() / 1000 - battleInfo.fireTime; - console.log(`当前箭已过${remain}秒`); - if (remain > 0 && remain < 15) { - // 等渲染好再通知 - setTimeout(() => { - uni.$emit("update-ramain", 15 - remain); - }, 300); - } - } - } else if (battleInfo.config.mode === 2) { - total.value = 90; - players.value = [...battleInfo.blueTeam, ...battleInfo.redTeam]; - players.value.forEach((p) => { - playersScores.value[p.id] = [...p.arrows]; - if (p.id === user.value.id) scores.value = [...p.arrows]; - }); - if (battleInfo.status === 2) { - startCount.value = true; - const remain = Date.now() / 1000 - battleInfo.startTime; - console.log(`当前局已进行${remain}秒`); - tips.value = battleInfo.halfGame - ? "下半场:请再射6箭" - : "上半场:请先射6箭"; - setTimeout(() => { - uni.$emit("update-ramain", 90 - remain); - }, 300); - } else if (battleInfo.status === 9) { - startCount.value = false; - tips.value = "准备下半场"; - setTimeout(() => { - uni.$emit("update-ramain", 0); - }, 300); - } - } -} async function refreshRoomData() { if (!roomNumber.value) return; @@ -275,29 +76,10 @@ async function refreshRoomData() { const startGame = async () => { const result = await startRoomAPI(room.value.number); - step.value = 2; }; async function onReceiveMessage(messages = []) { messages.forEach((msg) => { - if (msg.constructor === MESSAGETYPES.WaitForAllReady) { - if (refreshRoomTimer.value) clearInterval(refreshRoomTimer.value); - // 这里会掉多次; - battleId.value = msg.id; - step.value = 2; - if (battleType.value === 1) { - redTeam.value = msg.groupUserStatus.redTeam; - blueTeam.value = msg.groupUserStatus.blueTeam; - } else if (battleType.value === 2) { - players.value = [ - ...msg.groupUserStatus.redTeam, - ...msg.groupUserStatus.blueTeam, - ]; - players.value.forEach((p) => { - playersScores.value[p.id] = []; - }); - } - } if (msg.roomNumber === roomNumber.value) { if (msg.constructor === MESSAGETYPES.UserEnterRoom) { if (battleType.value === 1) { @@ -331,7 +113,7 @@ async function onReceiveMessage(messages = []) { } } } - if (!start.value && msg.constructor === MESSAGETYPES.UserExitRoom) { + if (msg.constructor === MESSAGETYPES.UserExitRoom) { if (battleType.value === 1) { if (msg.userId === room.value.creator) { owner.value = { @@ -347,7 +129,7 @@ async function onReceiveMessage(messages = []) { players.value = players.value.filter((p) => p.id !== msg.userId); } } - if (msg.constructor === MESSAGETYPES.RoomDestroy && !battleId.value) { + if (msg.constructor === MESSAGETYPES.RoomDestroy) { uni.showToast({ title: "房间已解散", icon: "none", @@ -358,138 +140,25 @@ async function onReceiveMessage(messages = []) { }, 1000); } } - if (msg.id === battleId.value) { - if (msg.constructor === MESSAGETYPES.AllReady) { - start.value = true; - totalRounds.value = msg.groupUserStatus.config.maxRounds; - step.value = 3; - roundResults.value.push({ - redArrows: [], - blueArrows: [], - }); - total.value = 15; - } - if (msg.constructor === MESSAGETYPES.MeleeAllReady) { - start.value = true; - startCount.value = true; - step.value = 3; - seq.value += 1; - tips.value = scores.value.length - ? "下半场:请再射6箭" - : "上半场:请先射6箭"; - total.value = 90; - halfTimeTip.value = false; - } - if (msg.constructor === MESSAGETYPES.ToSomeoneShoot) { - if (battleType.value === 1) { - if (currentShooterId.value !== msg.userId) { - seq.value += 1; - currentShooterId.value = msg.userId; - tips.value = - redTeam.value[0].id === currentShooterId.value - ? "请红队射箭 - " - : "请蓝队射箭 - "; - tips.value += isFinalShoot.value - ? "决金箭" - : `第${roundsName[currentRound.value]}轮`; - } - } - } - if (msg.constructor === MESSAGETYPES.ShootResult) { - if (battleType.value === 1) { - // 会有在蓝队射箭时间,红队射箭也有结果返回的情况 - if (currentShooterId.value !== msg.userId) return; - const isRed = redTeam.value.find((item) => item.id === msg.userId); - if (isRed) scores.value.push({ ...msg.target }); - else blueScores.value.push({ ...msg.target }); - if (!roundResults.value[currentRound.value - 1]) { - roundResults.value.push({ - redArrows: [], - blueArrows: [], - }); - } - roundResults.value[currentRound.value - 1][ - isRed ? "redArrows" : "blueArrows" - ].push({ ...msg.target }); - } - if (battleType.value === 2 && msg.userId === user.value.id) { - scores.value.push({ ...msg.target }); - power.value = msg.target.battery; - } - if (playersScores.value[msg.userId]) - playersScores.value[msg.userId].push({ ...msg.target }); - } - if (msg.constructor === MESSAGETYPES.CurrentRoundEnded) { - if (battleType.value === 1) { - const result = msg.preRoundResult; - scores.value = []; - blueScores.value = []; - currentShooterId.value = 0; - currentBluePoint.value = result.blueScore; - currentRedPoint.value = result.redScore; - bluePoints.value += result.blueScore; - redPoints.value += result.redScore; - uni.$emit("update-ramain", 0); - if (result.currentRound < 5) { - currentRound.value += 1; - roundResults.value.push({ - redArrows: [], - blueArrows: [], - }); - showRoundTip.value = true; - } - } - } - if (msg.constructor === MESSAGETYPES.FinalShoot) { - currentShooterId.value = 0; - currentRound.value += 1; - roundResults.value.push({ - redArrows: [], - blueArrows: [], - }); - if (!isFinalShoot.value) { - isFinalShoot.value = true; - showRoundTip.value = true; - tips.value = "准备开始决金箭"; - } - } - if (msg.constructor === MESSAGETYPES.HalfTimeOver) { - uni.$emit("update-ramain", 0); - [ + if (msg.constructor === MESSAGETYPES.WaitForAllReady) { + if (msg.groupUserStatus) { + uni.setStorageSync("red-team", msg.groupUserStatus.redTeam); + uni.setStorageSync("blue-team", msg.groupUserStatus.blueTeam); + uni.setStorageSync("melee-players", [ ...msg.groupUserStatus.redTeam, ...msg.groupUserStatus.blueTeam, - ].forEach((player) => { - playersScores.value[player.id] = [...player.arrows]; - if (player.id === user.value.id) scores.value = [...player.arrows]; - }); - startCount.value = false; - halfTimeTip.value = true; - tips.value = "准备下半场"; - } - if (msg.constructor === MESSAGETYPES.MatchOver) { - if (msg.endStatus.noSaved) { - // 正常每回合结束通知,回合会加上1 - currentRound.value += 1; - currentBluePoint.value = 0; - currentRedPoint.value = 0; - showRoundTip.value = true; - setTimeout(() => { - uni.navigateBack(); - }, 3000); - } else { - isEnded.value = true; - uni.setStorageSync("last-battle", msg.endStatus); - setTimeout(() => { - uni.redirectTo({ - url: "/pages/battle-result", - }); - }, 1500); + ]); + uni.removeStorageSync("current-battle"); + if (msg.groupUserStatus.config.mode == 1) { + uni.redirectTo({ + url: `/pages/team-match?battleId=${msg.id}&gameMode=1`, + }); + } else if (msg.groupUserStatus.config.mode == 2) { + uni.redirectTo({ + url: `/pages/melee-match?battleId=${msg.id}&gameMode=1`, + }); } } - if (msg.constructor === MESSAGETYPES.BackToGame) { - uni.$emit("update-header-loading", false); - if (msg.battleInfo) recoverData(msg.battleInfo); - } } }); } @@ -512,23 +181,11 @@ const setClipboardData = () => { }; const onBack = () => { - if (battleId.value) { - uni.$showHint(2); - } else { - showModal.value = true; - } + showModal.value = true; }; onLoad(async (options) => { - if (options.battleId) { - const battleInfo = uni.getStorageSync("current-battle"); - if (battleInfo) { - await nextTick(() => { - recoverData(battleInfo); - }); - setTimeout(getCurrentGameAPI, 2000); - } - } else if (options.roomNumber) { + if (options.roomNumber) { roomNumber.value = options.roomNumber; refreshRoomData(); refreshRoomTimer.value = setInterval(refreshRoomData, 2000); @@ -544,43 +201,24 @@ onMounted(() => { onUnmounted(() => { if (refreshRoomTimer.value) clearInterval(refreshRoomTimer.value); - if (refreshTimer.value) clearInterval(refreshTimer.value); uni.setKeepScreenOn({ keepScreenOn: false, }); uni.$off("socket-inbox", onReceiveMessage); - if (roomNumber.value && owner.value.id !== user.value.id && !battleId.value) { + if (roomNumber.value && owner.value.id !== user.value.id) { exitRoomAPI(roomNumber.value); } }); onShow(async () => { - if (battleId.value) { - if (!isEnded.value && (await isGameEnded(battleId.value))) return; - getCurrentGameAPI(); - const refreshData = () => { - const lastAwakeTime = uni.getStorageSync("last-awake-time"); - if (lastAwakeTime) getCurrentGameAPI(); - else clearInterval(refreshTimer.value); - }; - refreshTimer.value = setInterval(refreshData, 2000); - } else { - refreshRoomData(); - } -}); -onHide(() => { - if (refreshTimer.value) clearInterval(refreshTimer.value); - uni.setStorageSync("last-awake-time", Date.now()); + refreshRoomData(); }); +onHide(() => {});