新版房间1v1对战数据调试完成

This commit is contained in:
kron
2026-02-04 17:45:57 +08:00
parent a2674aae5b
commit 7f73f3ebb3
18 changed files with 524 additions and 843 deletions

View File

@@ -1,9 +1,9 @@
<script setup>
import { ref, onMounted } from "vue";
import { ref, computed, onMounted } from "vue";
import { onLoad } from "@dcloudio/uni-app";
import Avatar from "@/components/Avatar.vue";
import UserUpgrade from "@/components/UserUpgrade.vue";
import { getGameAPI } from "@/apis";
import { getBattleAPI } from "@/apis";
import { topThreeColors, getBattleResultTips } from "@/constants";
import audioManager from "@/audioManager";
import useStore from "@/store";
@@ -18,12 +18,7 @@ const totalPoints = ref(0);
const rank = ref(0);
function exit() {
const battleInfo = uni.getStorageSync("last-battle");
if (battleInfo && battleInfo.roomId) {
uni.redirectTo({
url: `/pages/battle-room?roomNumber=${battleInfo.roomId}`,
});
} else if (data.value.roomId) {
if (data.value.roomId) {
uni.redirectTo({
url: `/pages/battle-room?roomNumber=${data.value.roomId}`,
});
@@ -33,128 +28,87 @@ function exit() {
}
onLoad(async (options) => {
if (!options.battleId) return;
const myId = user.value.id;
if (options.battleId) {
const result = await getGameAPI(
options.battleId || "BATTLE-1758270367040321900-868"
const result = await getBattleAPI(options.battleId || "58351917302157312");
data.value = result;
if (result.winTeam) {
ifWin.value = result.teams[result.winTeam].players.some(
(p) => p.id === myId
);
data.value = {
...result,
battleMode: result.gameMode,
};
if (result.mode === 1) {
data.value.redPlayers = Object.values(result.redPlayers);
data.value.bluePlayers = Object.values(result.bluePlayers);
if (result.redPlayers[myId]) {
totalPoints.value = result.redPlayers[myId].totalScore;
data.value.myTeam = result.redPlayers[myId].team;
ifWin.value = result.winner === 0;
}
if (result.bluePlayers[myId]) {
totalPoints.value = result.bluePlayers[myId].totalScore;
data.value.myTeam = result.bluePlayers[myId].team;
ifWin.value = result.winner === 1;
}
}
if (result.mode === 2) {
data.value.playerStats = result.players.map((p) => ({
...p,
id: p.playerId,
}));
const mine = result.players.find((p) => p.playerId === myId);
if (mine) totalPoints.value = mine.totalScore;
rank.value = result.players.findIndex((p) => p.playerId === myId) + 1;
}
} else {
const battleInfo = uni.getStorageSync("last-battle");
if (!battleInfo) return;
data.value = {
mvps: [],
...battleInfo,
};
if (battleInfo.mode === 1) {
battleInfo.playerStats.forEach((p) => {
if (p.team === 1) data.value.bluePlayers = [p];
if (p.team === 0) data.value.redPlayers = [p];
if (p.mvp) data.value.mvps.push(p);
});
data.value.mvps.sort((a, b) => b.totalRings - a.totalRings);
}
rank.value = 0;
const mine = battleInfo.playerStats.find((p, index) => {
rank.value = index + 1;
return p.id === myId;
});
if (mine) {
data.value.myTeam = mine.team;
totalPoints.value = mine.totalScore;
if (battleInfo.mode === 1) {
ifWin.value = mine.team === battleInfo.winner;
}
}
}
if (data.value.mode === 1) {
if (result.way === 1) {
audioManager.play(ifWin.value ? "胜利" : "失败");
} else if (data.value.mode === 2) {
if (data.value.battleMode === 1) {
if (rank.value <= data.value.playerStats.length * 0.3) {
audioManager.play("胜利");
}
} else if (data.value.battleMode === 2) {
if (totalPoints.value > 0) {
audioManager.play("胜利");
} else if (totalPoints.value < 0) {
audioManager.play("失败");
}
}
} else if (result.way === 2) {
// if (data.value.battleMode === 1) {
// if (rank.value <= data.value.playerStats.length * 0.3) {
// audioManager.play("胜利");
// }
// } else if (data.value.battleMode === 2) {
// if (totalPoints.value > 0) {
// audioManager.play("胜利");
// } else if (totalPoints.value < 0) {
// audioManager.play("失败");
// }
// }
}
});
const myTeam = computed(() => {
const teams = data.value.teams;
if (teams && teams.length) {
if (teams[1].players.some((p) => p.id === user.value.id)) return 1;
}
return 2;
});
const checkBowData = () => {
uni.navigateTo({
url: `/pages/match-detail?id=${data.value.id}`,
url: `/pages/match-detail?id=${data.value.matchId}`,
});
};
</script>
<template>
<view class="container">
<block v-if="data.mode === 1">
<block v-if="data.way === 1">
<view class="header-team" :style="{ marginTop: '25%' }">
<image src="../static/battle-result.png" mode="widthFix" />
<view class="header-solo" v-if="data.teamSize === 2">
<view class="header-solo" v-if="data.mode === 1">
<text
:style="{
background:
data.winner === 1
data.winTeam === 1
? 'linear-gradient(270deg, #3597ff 0%, rgba(0,0,0,0) 100%);'
: 'linear-gradient(270deg, #fd4444 0%, rgba(0, 0, 0, 0) 100%)',
}"
>{{ data.winner === 1 ? "蓝队" : "红队" }}获胜</text
>{{ data.winTeam === 1 ? "蓝队" : "红队" }}获胜</text
>
<Avatar
:size="32"
:src="
data.winner === 1
? data.bluePlayers[0].avatar
: data.redPlayers[0].avatar
data.winTeam === 1
? data.teams[1].players[0].avatar
: data.teams[2].players[0].avatar
"
:borderColor="data.winner === 1 ? '#5FADFF' : '#FF5656'"
:borderColor="data.winTeam === 1 ? '#5FADFF' : '#FF5656'"
mode="widthFix"
/>
</view>
</view>
<view class="header-mvp" v-if="data.teamSize !== 2">
<view class="header-mvp" v-if="data.mode === 2 || data.mode === 3">
<image
:src="`../static/${data.winner === 1 ? 'blue' : 'red'}-team-win.png`"
:src="`../static/${data.winTeam === 1 ? 'blue' : 'red'}-team-win.png`"
mode="widthFix"
/>
<view
:style="{
transform: `translateY(50px) rotate(-${5 + data.mvps.length}deg)`,
transform: `translateY(50px) rotate(-${
5 + (data.mvp || []).length
}deg)`,
}"
>
<view v-if="data.mvps && data.mvps[0].totalRings">
<view v-if="data.mvp && data.mvp[0].totalRings">
<image src="../static/title-mvp.png" mode="widthFix" />
<text
>斩获<text
@@ -164,22 +118,22 @@ const checkBowData = () => {
margin: '0 3px',
fontWeight: '600',
}"
>{{ data.mvps[0].totalRings }}</text
>{{ data.mvp[0].totalRings }}</text
></text
>
</view>
<view v-if="data.mvps && data.mvps.length">
<view v-for="(player, index) in data.mvps" :key="index">
<view v-if="data.mvp && data.mvp.length">
<view v-for="(player, index) in data.mvp" :key="index">
<view class="team-avatar">
<Avatar
:src="player.avatar"
:size="40"
:borderColor="data.myTeam === 1 ? '#5fadff' : '#ff6060'"
:borderColor="myTeam === 1 ? '#5fadff' : '#ff6060'"
/>
<text
v-if="player.id === user.id"
:style="{
backgroundColor: data.myTeam === 1 ? '#5fadff' : '#ff6060',
backgroundColor: myTeam === 1 ? '#5fadff' : '#ff6060',
}"
>自己</text
>
@@ -198,7 +152,7 @@ const checkBowData = () => {
/>
<image
:src="
getBattleResultTips(data.battleMode, data.mode, {
getBattleResultTips(data.way, data.mode, {
win: ifWin,
})
"
@@ -207,7 +161,7 @@ const checkBowData = () => {
/>
</view>
</block>
<block v-if="data.mode === 2">
<block v-if="data.way === 2">
<view class="header-melee">
<view />
<image src="../static/battle-result.png" mode="widthFix" />
@@ -283,36 +237,36 @@ const checkBowData = () => {
</block>
<view
class="battle-e"
:style="{ marginTop: data.mode === 2 ? '20px' : '20vw' }"
:style="{ marginTop: data.way === 2 ? '20px' : '20vw' }"
>
<image src="../static/row-yellow-bg.png" mode="widthFix" />
<view class="team-avatar">
<Avatar
:src="user.avatar"
:size="40"
:borderColor="data.myTeam === 1 ? '#5fadff' : '#ff6060'"
:borderColor="myTeam === 1 ? '#5fadff' : '#ff6060'"
/>
<text
:style="{ backgroundColor: '#5fadff' }"
v-if="data.mode === 1 && data.myTeam === 1"
v-if="data.way === 1 && myTeam === 1"
>蓝队</text
>
<text
:style="{ backgroundColor: '#ff6060' }"
v-if="data.mode === 1 && data.myTeam === 0"
v-if="data.way === 1 && myTeam === 2"
>红队</text
>
</view>
<text v-if="data.battleMode === 1">
<text v-if="data.way === 1">
你的经验 {{ totalPoints > 0 ? "+" + totalPoints : totalPoints }}
</text>
<text v-if="data.battleMode === 2">
<text v-if="data.way === 2">
你的积分 {{ totalPoints > 0 ? "+" + totalPoints : totalPoints }}
</text>
</view>
<text v-if="data.mode === 2" class="description">
<text v-if="data.way === 2" class="description">
{{
getBattleResultTips(data.battleMode, data.mode, {
getBattleResultTips(data.way, data.mode, {
win: ifWin,
score: totalPoints,
rank,

View File

@@ -1,6 +1,6 @@
<script setup>
import { ref, watch, onMounted, onBeforeUnmount } from "vue";
import { onLoad, onShareAppMessage } from "@dcloudio/uni-app";
import { onShow, onLoad, onShareAppMessage } from "@dcloudio/uni-app";
import Container from "@/components/Container.vue";
import PlayerSeats from "@/components/PlayerSeats.vue";
import Guide from "@/components/Guide.vue";
@@ -16,7 +16,7 @@ import {
getReadyAPI,
} from "@/apis";
import { MESSAGETYPES } from "@/constants";
import { MESSAGETYPES, MESSAGETYPESV2 } from "@/constants";
import useStore from "@/store";
import { storeToRefs } from "pinia";
const store = useStore();
@@ -38,6 +38,7 @@ const allReady = ref(false);
const timer = ref(null);
async function refreshRoomData() {
if (!roomNumber.value) return;
const result = await getRoomAPI(roomNumber.value);
if (result.started) return;
room.value = result;
@@ -94,7 +95,7 @@ async function refreshRoomData() {
refreshMembers(result.members);
}
if (timer.value) clearInterval(timer.value);
timer.value = setTimeout(refreshRoomData, 1000);
// timer.value = setTimeout(refreshRoomData, 2000);
}
const startGame = async () => {
@@ -122,9 +123,10 @@ const refreshMembers = (members = []) => {
}
};
async function onReceiveMessage(messages = []) {
messages.forEach((msg) => {
if (msg.roomNumber === roomNumber.value) {
async function onReceiveMessage(message) {
if (Array.isArray(message)) {
message.forEach((msg) => {
if (msg.roomNumber !== roomNumber.value) return;
if (msg.constructor === MESSAGETYPES.UserEnterRoom) {
if (battleType.value === 1) {
if (msg.userId === room.value.creator) {
@@ -193,29 +195,45 @@ async function onReceiveMessage(messages = []) {
} else if (msg.constructor === MESSAGETYPES.SomeoneIsReady) {
refreshRoomData();
}
} else 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,
]);
uni.removeStorageSync("current-battle");
// 避免离开页面,触发退出房间
roomNumber.value = "";
if (msg.groupUserStatus.config.mode == 1) {
uni.redirectTo({
url: `/pages/team-battle?battleId=${msg.id}&gameMode=1`,
});
} else if (msg.groupUserStatus.config.mode == 2) {
uni.redirectTo({
url: `/pages/melee-match?battleId=${msg.id}&gameMode=1`,
});
}
}
// else 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,
// ]);
// uni.removeStorageSync("current-battle");
// // 避免离开页面,触发退出房间
// roomNumber.value = "";
// if (msg.groupUserStatus.config.mode == 1) {
// uni.redirectTo({
// url: `/pages/team-battle?battleId=${msg.id}&gameMode=1`,
// });
// } else if (msg.groupUserStatus.config.mode == 2) {
// uni.redirectTo({
// url: `/pages/melee-match?battleId=${msg.id}&gameMode=1`,
// });
// }
// }
// }
});
} else if (message.type === MESSAGETYPESV2.AboutToStart) {
uni.setStorageSync("blue-team", message.teams[1].players || []);
uni.setStorageSync("red-team", message.teams[2].players || []);
uni.removeStorageSync("current-battle");
roomNumber.value = "";
let params = `?gameMode=1&battleId=${message.matchId}`;
if (message.way == 1) {
uni.redirectTo({
url: "/pages/team-battle" + params,
});
} else if (message.way == 2) {
uni.redirectTo({
url: "/pages/melee-match" + params,
});
}
});
}
}
const chooseTeam = async (team) => {
@@ -254,11 +272,12 @@ onShareAppMessage(() => {
};
});
onShow(() => {
refreshRoomData();
});
onLoad(async (options) => {
if (options.roomNumber) {
roomNumber.value = options.roomNumber;
refreshRoomData();
}
if (options.roomNumber) roomNumber.value = options.roomNumber;
});
onMounted(() => {

View File

@@ -23,6 +23,7 @@ const warnning = ref("");
const roomNumber = ref("");
const data = ref({});
const roomID = ref("");
const loading = ref(false);
const enterRoom = debounce(async (number) => {
if (!canEenter(user.value, device.value, online.value)) return;
@@ -33,27 +34,32 @@ const enterRoom = debounce(async (number) => {
if (!number) {
warnning.value = "请输入房间号";
showModal.value = true;
} else {
return;
}
try {
const room = await getRoomAPI(number);
if (room.number) {
const alreadyIn = room.members.find(
(item) => item.userInfo.id === user.value.id
);
if (!alreadyIn) {
const result = await joinRoomAPI(number);
if (result.full) {
warnning.value = "房间已满员";
showModal.value = true;
return;
}
}
uni.navigateTo({
url: "/pages/battle-room?roomNumber=" + number,
});
} else {
if (!room.number) {
warnning.value = room.started ? "该房间对战已开始,无法加入" : "查无此房";
showModal.value = true;
return;
}
const alreadyIn = room.members.find(
(item) => item.userInfo.id === user.value.id
);
if (!alreadyIn) {
const result = await joinRoomAPI(number);
if (result.full) {
warnning.value = "房间已满员";
showModal.value = true;
return;
}
}
loading.value = true;
uni.navigateTo({
url: "/pages/battle-room?roomNumber=" + number,
});
} finally {
loading.value = false;
}
});
const onCreateRoom = async () => {

View File

@@ -5,7 +5,7 @@ import Container from "@/components/Container.vue";
import BattleHeader from "@/components/BattleHeader.vue";
import Avatar from "@/components/Avatar.vue";
import PlayerScore2 from "@/components/PlayerScore2.vue";
import { getGameAPI } from "@/apis";
import { getBattleAPI } from "@/apis";
const blueTeam = ref([]);
const redTeam = ref([]);
@@ -13,79 +13,23 @@ const roundsData = ref([]);
const goldenRoundsData = ref([]);
const battleId = ref("");
const data = ref({
players: [],
teams: [],
rounds: [],
});
onLoad(async (options) => {
if (options.id) {
battleId.value = options.id || "BATTLE-1755484626207409508-955";
const result = await getGameAPI(battleId.value);
data.value = result;
if (result.mode === 1) {
blueTeam.value = Object.values(result.bluePlayers || {});
redTeam.value = Object.values(result.redPlayers || {});
Object.values(result.roundsData).forEach((item) => {
let bluePoint = 1;
let redPoint = 1;
let blueTotalRings = 0;
let redTotalRings = 0;
let blueArrows = [];
let redArrows = [];
blueTeam.value.forEach((p) => {
if (!item[p.playerId]) return;
blueTotalRings += item[p.playerId].reduce((a, b) => a + b.ring, 0);
blueArrows = [...blueArrows, ...item[p.playerId]];
});
redTeam.value.forEach((p) => {
if (!item[p.playerId]) return;
redTotalRings += item[p.playerId].reduce((a, b) => a + b.ring, 0);
redArrows = [...redArrows, ...item[p.playerId]];
});
if (blueTotalRings > redTotalRings) {
bluePoint = 2;
redPoint = 0;
} else if (blueTotalRings < redTotalRings) {
bluePoint = 0;
redPoint = 2;
}
roundsData.value.push({
blue: {
avatars: blueTeam.value.map((p) => p.avatar),
arrows: blueArrows,
totalRing: blueTotalRings,
totalScore: bluePoint,
},
red: {
avatars: redTeam.value.map((p) => p.avatar),
arrows: redArrows,
totalRing: redTotalRings,
totalScore: redPoint,
},
});
});
result.goldenRounds.forEach((round) => {
goldenRoundsData.value.push({
blue: {
avatars: blueTeam.value.map((p) => p.avatar),
arrows: round.arrowHistory.filter((a) => a.team === 1),
},
red: {
avatars: redTeam.value.map((p) => p.avatar),
arrows: round.arrowHistory.filter((a) => a.team === 0),
},
winner: round.winner,
});
});
}
}
if (!options.id) return;
battleId.value = options.id || "57943107462893568";
const result = await getBattleAPI(battleId.value);
data.value = result;
});
const checkBowData = () => {
if (data.value.mode === 1) {
const checkBowData = (selected) => {
if (data.value.way === 1) {
uni.navigateTo({
url: `/pages/team-bow-data?battleId=${battleId.value}`,
url: `/pages/team-bow-data?battleId=${battleId.value}&selected=${selected}`,
});
} else if (data.value.mode === 2) {
} else if (data.value.way === 2) {
uni.navigateTo({
url: `/pages/melee-bow-data?battleId=${battleId.value}`,
});
@@ -97,13 +41,13 @@ const checkBowData = () => {
<Container title="详情">
<view class="container">
<BattleHeader
:winner="data.winner"
:blueTeam="blueTeam"
:redTeam="redTeam"
:winner="data.winTeam"
:blueTeam="data.teams[1] ? data.teams[1].players : []"
:redTeam="data.teams[2] ? data.teams[2].players : []"
:players="data.players"
/>
<view
v-if="data.players && data.players.length"
v-if="data.mode > 3"
class="score-header"
:style="{ border: 'none', padding: '5px 15px' }"
>
@@ -114,7 +58,7 @@ const checkBowData = () => {
</view>
</view>
<PlayerScore2
v-if="data.players && data.players.length"
v-if="data.mode > 3"
v-for="(player, index) in data.players"
:key="index"
:name="player.name"
@@ -124,131 +68,47 @@ const checkBowData = () => {
:totalRing="player.totalRings"
:rank="index + 1"
/>
<block v-for="(round, index) in goldenRoundsData" :key="index">
<view
v-for="(round, index) in data.rounds"
:key="index"
:style="{ marginBottom: '5px' }"
>
<view class="score-header">
<text>决金箭轮环数</text>
<view @click="checkBowData">
<text>{{ round.ifGold ? "决金箭" : `${index + 1}` }}</text>
<view @click="() => checkBowData(index)">
<text>查看靶纸</text>
<image src="../static/back.png" mode="widthFix" />
</view>
</view>
<view class="score-row">
<view
class="score-row"
v-for="team in Object.keys(round.shoots)"
:key="team"
>
<view>
<view>
<image
v-for="(src, index) in round.blue.avatars"
v-for="(p, index) in data.teams[team].players"
:style="{
borderColor: '#64BAFF',
transform: `translateX(-${index * 15}px)`,
}"
:src="src"
:src="p.avatar || '../static/user-icon.png'"
:key="index"
mode="widthFix"
/>
</view>
<text v-for="(arrow, index) in round.blue.arrows" :key="index">
<text v-for="(arrow, index2) in round.shoots[team]" :key="index2">
{{ arrow.ring }}
</text>
</view>
<image
v-if="round.winner === 1"
src="../static/winner-badge.png"
mode="widthFix"
/>
</view>
<view class="score-row" :style="{ marginBottom: '5px' }">
<view>
<view>
<image
v-for="(src, index) in round.red.avatars"
:style="{
borderColor: '#FF6767',
transform: `translateX(-${index * 15}px)`,
}"
:src="src || '../static/user-icon.png'"
:key="index"
mode="widthFix"
/>
</view>
<text v-for="(arrow, index) in round.red.arrows" :key="index">
{{ arrow.ring }}
<text :style="{ color: team == 1 ? '#64BAFF' : '#FF6767' }">
{{ round.shoots[team].reduce((acc, cur) => acc + cur.ring, 0) }}
</text>
<text>得分 {{ round.scores[team].totalRing }}</text>
</view>
<image
v-if="round.winner === 0"
src="../static/winner-badge.png"
mode="widthFix"
/>
</view>
</block>
<view
v-for="(round, index) in roundsData"
:key="index"
:style="{ marginBottom: '5px' }"
>
<block
v-if="
index < Object.keys(roundsData).length - goldenRoundsData.length
"
>
<view class="score-header">
<text>第{{ index + 1 }}轮</text>
<view @click="checkBowData">
<text>查看靶纸</text>
<image src="../static/back.png" mode="widthFix" />
</view>
</view>
<view class="score-row">
<view>
<view>
<image
v-for="(src, index) in round.blue.avatars"
:style="{
borderColor: '#64BAFF',
transform: `translateX(-${index * 15}px)`,
}"
:src="src || '../static/user-icon.png'"
:key="index"
mode="widthFix"
/>
</view>
<text v-for="(arrow, index2) in round.blue.arrows" :key="index2">
{{ arrow.ring }}环
</text>
</view>
<view>
<text :style="{ color: '#64BAFF' }">
{{ round.blue.totalRing }}环
</text>
<text>得分 {{ round.blue.totalScore }}</text>
</view>
</view>
<view class="score-row">
<view>
<view>
<image
v-for="(src, index) in round.red.avatars"
:style="{
borderColor: '#FF6767',
transform: `translateX(-${index * 15}px)`,
}"
:src="src || '../static/user-icon.png'"
:key="index"
mode="widthFix"
/>
</view>
<text v-for="(arrow, index2) in round.red.arrows" :key="index2">
{{ arrow.ring }}环
</text>
</view>
<view>
<text :style="{ color: '#FF6767' }">
{{ round.red.totalRing }}环
</text>
<text>得分 {{ round.red.totalScore }}</text>
</view>
</view>
</block>
</view>
<view :style="{ height: '20px' }"></view>
</view>

View File

@@ -75,13 +75,13 @@ function recoverData(battleInfo) {
? "下半场请再射6箭"
: "上半场请先射6箭";
setTimeout(() => {
uni.$emit("update-ramain", 90 - remain);
uni.$emit("update-remain", 90 - remain);
}, 200);
} else if (battleInfo.status === 9) {
startCount.value = false;
tips.value = "准备下半场";
setTimeout(() => {
uni.$emit("update-ramain", 0);
uni.$emit("update-remain", 0);
}, 200);
}
}
@@ -131,7 +131,7 @@ async function onReceiveMessage(messages = []) {
playersScores.value[msg.userId].push({ ...msg.target });
}
if (msg.constructor === MESSAGETYPES.HalfTimeOver) {
uni.$emit("update-ramain", 0);
uni.$emit("update-remain", 0);
[...msg.groupUserStatus.redTeam, ...msg.groupUserStatus.blueTeam].forEach(
(player) => {
playersScores.value[player.id] = [...player.arrows];

View File

@@ -12,18 +12,18 @@ import RoundEndTip from "@/components/RoundEndTip.vue";
import TestDistance from "@/components/TestDistance.vue";
import TeamAvatars from "@/components/TeamAvatars.vue";
import ShootProgress2 from "@/components/ShootProgress2.vue";
import { getCurrentGameAPI, laserCloseAPI } from "@/apis";
import { isGameEnded } from "@/util";
import { MESSAGETYPES, roundsName } from "@/constants";
import { getCurrentGameAPI, laserCloseAPI, getBattleAPI } from "@/apis";
import { isGameEnded, formatTimestamp } from "@/util";
import { MESSAGETYPES, MESSAGETYPESV2, roundsName } from "@/constants";
import audioManager from "@/audioManager";
import useStore from "@/store";
import { storeToRefs } from "pinia";
const store = useStore();
const { user } = storeToRefs(store);
const start = ref(false);
const start = ref(null);
const tips = ref("");
const battleId = ref("");
const currentRound = ref(1);
const currentRound = ref(0);
const goldenRound = ref(0);
const currentRedPoint = ref(0);
const currentBluePoint = ref(0);
@@ -37,246 +37,95 @@ const redPoints = ref(0);
const bluePoints = ref(0);
const showRoundTip = ref(false);
const isFinalShoot = ref(false);
const isEnded = ref(false);
function recoverData(battleInfo) {
uni.removeStorageSync("last-awake-time");
battleId.value = battleInfo.id;
redTeam.value = battleInfo.redTeam;
blueTeam.value = battleInfo.blueTeam;
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);
}
} else {
start.value = true;
bluePoints.value = 0;
redPoints.value = 0;
currentRound.value = battleInfo.currentRound;
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;
const recoverData = (battleInfo, { force = false, arrowOnly = false } = {}) => {
try {
battleId.value = battleInfo.matchId;
blueTeam.value = battleInfo.teams[1].players || [];
redTeam.value = battleInfo.teams[2].players || [];
if (battleInfo.status === 0) {
start.value = false;
const readyRemain = (Date.now() - battleInfo.createTime) / 1000;
console.log(`对局已进行${readyRemain}`);
if (readyRemain > 0 && readyRemain < 15) {
setTimeout(() => {
uni.$emit("update-timer", 15 - readyRemain - 0.2);
}, 200);
}
});
if (battleInfo.goldenRoundNumber) {
currentRound.value += battleInfo.goldenRoundNumber;
goldenRound.value = battleInfo.goldenRoundNumber;
isFinalShoot.value = true;
for (let i = 1; i <= battleInfo.goldenRoundNumber; i++) {
const redArrows = [];
battleInfo.redTeam.forEach((item) => {
if (item.shotHistory[roundResults.value.length + 1]) {
item.shotHistory[roundResults.value.length + 1]
.filter((item) => !!item.playerId)
.forEach((item) => redArrows.push(item));
}
});
const blueArrows = [];
battleInfo.blueTeam.forEach((item) => {
if (item.shotHistory[roundResults.value.length + 1]) {
item.shotHistory[roundResults.value.length + 1]
.filter((item) => !!item.playerId)
.forEach((item) => blueArrows.push(item));
}
});
roundResults.value.push({
number: roundResults.value.length + 1,
blueArrows,
redArrows,
blueTotal: blueArrows.reduce((last, next) => last + next.ring, 0),
redTotal: redArrows.reduce((last, next) => last + next.ring, 0),
});
}
} else {
const hasCurrentRoundData =
battleInfo.redTeam.some(
(item) => !!item.shotHistory[battleInfo.currentRound]
) ||
battleInfo.blueTeam.some(
(item) => !!item.shotHistory[battleInfo.currentRound]
);
if (
battleInfo.currentRound > battleInfo.roundResults.length &&
hasCurrentRoundData
) {
const blueArrows = [];
const redArrows = [];
battleInfo.redTeam.forEach((item) =>
item.shotHistory[battleInfo.currentRound]
.filter((item) => !!item.playerId)
.forEach((item) => redArrows.push(item))
);
battleInfo.blueTeam.forEach((item) =>
item.shotHistory[battleInfo.currentRound]
.filter((item) => !!item.playerId)
.forEach((item) => blueArrows.push(item))
);
roundResults.value.push({
redArrows,
blueArrows,
});
}
[...battleInfo.redTeam, ...battleInfo.blueTeam].some((p) => {
if (p.id === user.value.id) {
const roundArrows = Object.values(p.shotHistory);
if (roundArrows.length) {
uni.$emit("update-shot", {
currentShot: roundArrows[roundArrows.length - 1].length,
totalShot: battleInfo.config.teamSize === 2 ? 3 : 2,
});
}
return true;
}
return false;
});
return;
}
const lastIndex = roundResults.value.length - 1;
if (roundResults.value[lastIndex]) {
const redArrows = roundResults.value[lastIndex].redArrows;
scores.value = [...redArrows]
.filter((item) => !!item.playerId)
.sort((a, b) => a.shotTimeUnix - b.shotTimeUnix);
const blueArrows = roundResults.value[lastIndex].blueArrows;
blueScores.value = [...blueArrows]
.filter((item) => !!item.playerId)
.sort((a, b) => a.shotTimeUnix - b.shotTimeUnix);
}
if (battleInfo.firePlayerIndex) {
currentShooterId.value = battleInfo.firePlayerIndex;
const redPlayer = redTeam.value.find(
(item) => item.id === currentShooterId.value
if (!arrowOnly) {
start.value = true;
currentShooterId.value = battleInfo.current.playerId;
const redPlayer = battleInfo.teams[2].players.find(
(item) => item.id === battleInfo.current.playerId
);
let nextTips = redPlayer ? "请红队射箭" : "请蓝队射箭";
nextTips += "重回";
// if (battleInfo.firePlayerIndex === user.value.id) nextTips += "你";
if (force) nextTips += "重回";
if (
battleInfo.current.playerId === user.value.id &&
redTeam.value.length > 1
) {
nextTips += "你";
}
tips.value = nextTips;
uni.$emit("update-tips", nextTips);
}
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);
}
}
}
}
async function onReceiveMessage(messages = []) {
messages.forEach((msg) => {
if (msg.constructor === MESSAGETYPES.WaitForAllReady) {
redTeam.value = msg.groupUserStatus.redTeam;
blueTeam.value = msg.groupUserStatus.blueTeam;
}
if (msg.constructor === MESSAGETYPES.AllReady) {
start.value = true;
}
if (msg.constructor === MESSAGETYPES.ToSomeoneShoot) {
if (currentShooterId.value !== msg.userId) {
currentShooterId.value = msg.userId;
const redPlayer = redTeam.value.find(
(item) => item.id === currentShooterId.value
if (force) {
const remain = (Date.now() - battleInfo.current.startTime) / 1000;
console.log(
`当前轮已进行${remain},${Date.now()},${
battleInfo.current.startTimeText
}`
);
let nextTips = redPlayer ? "请红队射箭" : "请蓝队射箭";
if (msg.userId === user.value.id && redTeam.value.length > 1) {
nextTips += "你";
if (remain > 0 && remain < 15) {
setTimeout(() => {
uni.$emit("update-remain", 15 - remain - 0.2);
}, 200);
}
if (nextTips !== tips.value) {
tips.value = nextTips;
uni.$emit("update-tips", tips.value);
} else {
uni.$emit("update-ramain", 15);
}
}
}
if (msg.constructor === MESSAGETYPES.ShootResult) {
if (msg.battleInfo) recoverData(msg.battleInfo);
}
if (msg.constructor === MESSAGETYPES.CurrentRoundEnded) {
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;
if (!result.goldenRound) {
showRoundTip.value = true;
}
}
if (msg.constructor === MESSAGETYPES.FinalShoot) {
currentShooterId.value = 0;
currentBluePoint.value = bluePoints.value;
currentRedPoint.value = redPoints.value;
if (!isFinalShoot.value) {
isFinalShoot.value = true;
showRoundTip.value = true;
tips.value = "准备开始决金箭";
}
}
if (msg.constructor === MESSAGETYPES.MatchOver) {
if (msg.endStatus.noSaved) {
currentBluePoint.value = 0;
currentRedPoint.value = 0;
showRoundTip.value = true;
isFinalShoot.value = false;
setTimeout(() => {
uni.navigateBack();
}, 3000);
} else {
isEnded.value = true;
uni.setStorageSync("last-battle", msg.endStatus);
setTimeout(() => {
uni.redirectTo({
url: "/pages/battle-result",
});
}, 1000);
uni.$emit("update-remain", battleInfo.readyTime);
}
} else {
currentRound.value = battleInfo.current.round || 1;
const latestRound = battleInfo.rounds[currentRound.value - 1];
if (latestRound) {
blueScores.value = latestRound.shoots[1];
scores.value = latestRound.shoots[2];
}
}
if (msg.constructor === MESSAGETYPES.BackToGame) {
uni.$emit("update-header-loading", false);
if (msg.battleInfo) recoverData(msg.battleInfo);
roundResults.value = battleInfo.rounds || [];
isFinalShoot.value = battleInfo.current.goldRound;
bluePoints.value = battleInfo.teams[1].score;
redPoints.value = battleInfo.teams[2].score;
} catch (err) {
console.log(err);
}
};
async function onReceiveMessage(msg) {
if (Array.isArray(msg)) return;
if (msg.type === MESSAGETYPESV2.BattleStart) {
start.value = true;
} else if (msg.type === MESSAGETYPESV2.ToSomeoneShoot) {
recoverData(msg);
} else if (msg.type === MESSAGETYPESV2.ShootResult) {
recoverData(msg, { arrowOnly: true });
} else if (msg.type === MESSAGETYPESV2.NewRound) {
showRoundTip.value = true;
const latestRound = msg.rounds[currentRound.value - 1];
if (latestRound) {
currentBluePoint.value = latestRound.scores[1].score;
currentRedPoint.value = latestRound.scores[2].score;
}
});
} else if (msg.type === MESSAGETYPESV2.BattleEnd) {
uni.redirectTo({
url: "/pages/battle-result?battleId=" + msg.matchId,
});
}
}
onLoad(async (options) => {
if (options.battleId) {
battleId.value = options.battleId;
redTeam.value = uni.getStorageSync("red-team");
blueTeam.value = uni.getStorageSync("blue-team");
const battleInfo = uni.getStorageSync("current-battle");
if (battleInfo) {
await nextTick(() => {
recoverData(battleInfo);
});
setTimeout(getCurrentGameAPI, 2000);
}
}
if (options.battleId) battleId.value = options.battleId;
uni.enableAlertBeforeUnload({
message: "离开比赛可能导致比赛失败,是否继续?",
success: (res) => {
@@ -301,30 +150,46 @@ onBeforeUnmount(() => {
const refreshTimer = ref(null);
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);
const result = await getBattleAPI(battleId.value);
if (result.status === 2) {
uni.showToast({
title: "比赛已结束",
icon: "none",
});
uni.navigateBack({
delta: 2,
});
} else {
recoverData(result, { force: true });
}
// if (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);
}
});
onHide(() => {
if (refreshTimer.value) clearInterval(refreshTimer.value);
uni.setStorageSync("last-awake-time", Date.now());
});
// onHide(() => {
// if (refreshTimer.value) clearInterval(refreshTimer.value);
// uni.setStorageSync("last-awake-time", Date.now());
// });
</script>
<template>
<Container :bgType="start ? 3 : 1">
<view class="container">
<BattleHeader v-if="!start" :redTeam="redTeam" :blueTeam="blueTeam" />
<TestDistance v-if="!start" :guide="false" :isBattle="true" />
<BattleHeader
v-if="start === false"
:redTeam="redTeam"
:blueTeam="blueTeam"
/>
<TestDistance v-if="start === false" :guide="false" :isBattle="true" />
<view v-if="start" class="players-row">
<TeamAvatars
:team="blueTeam"

View File

@@ -5,105 +5,42 @@ import Container from "@/components/Container.vue";
import BowTarget from "@/components/BowTarget.vue";
import Avatar from "@/components/Avatar.vue";
import { roundsName } from "@/constants";
import { getGameAPI } from "@/apis";
import { getBattleAPI } from "@/apis";
const selected = ref(0);
const redScores = ref([]);
const blueScores = ref([]);
const tabs = ref(["所有轮次"]);
const tabs = ref([]);
const players = ref([]);
const allRoundsScore = ref({});
const data = ref({
goldenRounds: [],
});
const data = ref({});
const loadArrows = (round) => {
round.shoots[1].forEach((arrow) => {
blueScores.value.push(arrow);
});
round.shoots[2].forEach((arrow) => {
redScores.value.push(arrow);
});
};
onLoad(async (options) => {
if (options.battleId) {
const result = await getGameAPI(
options.battleId || "BATTLE-1756453741433684760-512"
);
data.value = result;
Object.values(result.bluePlayers).forEach((p, index) => {
players.value.push(p);
if (
Object.values(result.redPlayers) &&
Object.values(result.redPlayers)[index]
) {
players.value.push(Object.values(result.redPlayers)[index]);
}
});
if (result.goldenRounds) {
result.goldenRounds.forEach(() => {
tabs.value.push("决金箭");
});
}
Object.keys(result.roundsData).forEach((key, index) => {
if (
index <
Object.keys(result.roundsData).length - result.goldenRounds.length
) {
tabs.value.push(`${roundsName[key]}`);
}
});
onClickTab(0);
}
if (!options.battleId) return;
const result = await getBattleAPI(options.battleId || "57943107462893568");
data.value = result;
data.value.teams[1].players.forEach((p, index) => {
players.value.push(p);
players.value.push(data.value.teams[2].players[index]);
});
Object.values(data.value.rounds).forEach((round, index) => {
if (round.ifGold) tabs.value.push(`决金箭`);
else tabs.value.push(`${roundsName[index + 1]}`);
});
selected.value = Number(options.selected || 0);
onClickTab(selected.value);
});
const onClickTab = (index) => {
selected.value = index;
redScores.value = [];
blueScores.value = [];
const { bluePlayers, redPlayers, roundsData, goldenRounds } = data.value;
let maxArrowLength = 0;
if (index === 0) {
Object.keys(bluePlayers).forEach((p) => {
allRoundsScore.value[p] = [];
Object.values(roundsData).forEach((round) => {
if (!round[p]) return;
allRoundsScore.value[p].push(
round[p].reduce((last, next) => last + next.ring, 0)
);
round[p].forEach((arrow) => {
blueScores.value.push(arrow);
});
});
});
Object.keys(redPlayers).forEach((p) => {
allRoundsScore.value[p] = [];
Object.values(roundsData).forEach((round) => {
if (!round[p]) return;
allRoundsScore.value[p].push(
round[p].reduce((last, next) => last + next.ring, 0)
);
round[p].forEach((arrow) => {
redScores.value.push(arrow);
});
});
});
} else if (index <= goldenRounds.length) {
const dataIndex =
Object.keys(roundsData).length - goldenRounds.length + index;
Object.keys(bluePlayers).forEach((p) => {
if (!roundsData[dataIndex][p]) return;
roundsData[dataIndex][p].forEach((arrow) => {
blueScores.value.push(arrow);
});
});
Object.keys(redPlayers).forEach((p) => {
if (!roundsData[dataIndex][p]) return;
roundsData[dataIndex][p].forEach((arrow) => {
redScores.value.push(arrow);
});
});
} else {
Object.keys(bluePlayers).forEach((p) => {
roundsData[index - goldenRounds.length][p].forEach((arrow) => {
blueScores.value.push(arrow);
});
});
Object.keys(redPlayers).forEach((p) => {
roundsData[index - goldenRounds.length][p].forEach((arrow) => {
redScores.value.push(arrow);
});
});
}
loadArrows(data.value.rounds[index]);
};
</script>
@@ -134,41 +71,14 @@ const onClickTab = (index) => {
>
<Avatar
:src="player.avatar"
:borderColor="
data.bluePlayers[player.playerId] ? '#64BAFF' : '#FF6767'
"
:borderColor="index % 2 === 0 ? '#64BAFF' : '#FF6767'"
:size="36"
/>
<view>
<view
v-if="selected === 0"
v-for="(ring, index) in allRoundsScore[player.playerId]"
:key="index"
class="score-item"
>
{{ ring }}
</view>
<view
v-if="
selected > 0 &&
selected >= data.goldenRounds.length &&
selected <= data.goldenRounds.length
"
v-for="(score, index) in data.roundsData[
Object.keys(data.roundsData).length -
data.goldenRounds.length +
selected
][player.playerId]"
:key="index"
class="score-item"
>
{{ score.ring }}
</view>
<view
v-if="selected > data.goldenRounds.length"
v-for="(score, index) in data.roundsData[
selected - data.goldenRounds.length
][player.playerId]"
v-for="(score, index) in data.rounds[selected].shoots[
index % 2 === 0 ? 1 : 2
]"
:key="index"
class="score-item"
>