完成打乱斗数据调试
This commit is contained in:
@@ -417,12 +417,6 @@ export const getUserGameState = () => {
|
|||||||
return request("GET", "/user/state");
|
return request("GET", "/user/state");
|
||||||
};
|
};
|
||||||
|
|
||||||
export const getCurrentGameAPI = async () => {
|
|
||||||
// uni.$emit("update-header-loading", true);
|
|
||||||
// const result = await request("GET", "/user/join/battle");
|
|
||||||
// return result.currentGame || {};
|
|
||||||
};
|
|
||||||
|
|
||||||
export const getPointBookConfigAPI = async () => {
|
export const getPointBookConfigAPI = async () => {
|
||||||
return request("GET", "/user/score/sheet/option");
|
return request("GET", "/user/score/sheet/option");
|
||||||
};
|
};
|
||||||
@@ -554,8 +548,7 @@ export const getReadyAPI = (roomId) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export const getBattleAPI = async (battleId) => {
|
export const getBattleAPI = async (battleId) => {
|
||||||
const result = await request("POST", "/user/match/info", {
|
return request("POST", "/user/match/info", {
|
||||||
id: battleId,
|
id: battleId,
|
||||||
});
|
});
|
||||||
return result;
|
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -46,14 +46,14 @@ const onClick = debounce(async () => {
|
|||||||
loading.value = true;
|
loading.value = true;
|
||||||
const result = await getBattleAPI();
|
const result = await getBattleAPI();
|
||||||
if (result && result.matchId) {
|
if (result && result.matchId) {
|
||||||
// await uni.$checkAudio();
|
await uni.$checkAudio();
|
||||||
if (result.way === 1) {
|
if (result.mode <= 3) {
|
||||||
uni.navigateTo({
|
uni.navigateTo({
|
||||||
url: `/pages/team-battle?battleId=${result.matchId}`,
|
url: `/pages/team-battle?battleId=${result.matchId}`,
|
||||||
});
|
});
|
||||||
} else if (result.way === 2) {
|
} else {
|
||||||
uni.navigateTo({
|
uni.navigateTo({
|
||||||
url: `/pages/melee-match?battleId=${result.matchId}`,
|
url: `/pages/melee-battle?battleId=${result.matchId}`,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import AppBackground from "@/components/AppBackground.vue";
|
|||||||
import Header from "@/components/Header.vue";
|
import Header from "@/components/Header.vue";
|
||||||
import ScreenHint from "@/components/ScreenHint.vue";
|
import ScreenHint from "@/components/ScreenHint.vue";
|
||||||
import BackToGame from "@/components/BackToGame.vue";
|
import BackToGame from "@/components/BackToGame.vue";
|
||||||
import { getCurrentGameAPI, laserAimAPI } from "@/apis";
|
import { laserAimAPI, getBattleAPI } from "@/apis";
|
||||||
import { capsuleHeight, debounce } from "@/util";
|
import { capsuleHeight, debounce } from "@/util";
|
||||||
import AudioManager from "@/audioManager";
|
import AudioManager from "@/audioManager";
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
@@ -111,15 +111,19 @@ const backToGame = debounce(async () => {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
isLoading.value = true;
|
isLoading.value = true;
|
||||||
const game = await getCurrentGameAPI();
|
const result = await getBattleAPI();
|
||||||
if (!game || !game.gameId) {
|
if (result && result.matchId) {
|
||||||
uni.showToast({
|
await checkAudioProgress();
|
||||||
title: "没有进行中的对局",
|
if (result.mode <= 3) {
|
||||||
icon: "none",
|
uni.navigateTo({
|
||||||
});
|
url: `/pages/team-battle?battleId=${result.matchId}`,
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
uni.navigateTo({
|
||||||
|
url: `/pages/melee-battle?battleId=${result.matchId}`,
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
showHint.value = false;
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("获取当前游戏失败:", error);
|
console.error("获取当前游戏失败:", error);
|
||||||
} finally {
|
} finally {
|
||||||
|
|||||||
@@ -44,6 +44,8 @@ const createRoom = debounce(async () => {
|
|||||||
url: "/pages/battle-room?roomNumber=" + result.number,
|
url: "/pages/battle-room?roomNumber=" + result.number,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.log(error);
|
||||||
} finally {
|
} finally {
|
||||||
loading.value = false;
|
loading.value = false;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -56,7 +56,6 @@ const signin = () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const loading = ref(false);
|
const loading = ref(false);
|
||||||
const showLoader = ref(false);
|
|
||||||
const pointBook = ref(null);
|
const pointBook = ref(null);
|
||||||
const showProgress = ref(false);
|
const showProgress = ref(false);
|
||||||
const heat = ref(0);
|
const heat = ref(0);
|
||||||
@@ -80,20 +79,12 @@ onMounted(() => {
|
|||||||
pointBook.value = uni.getStorageSync("last-point-book");
|
pointBook.value = uni.getStorageSync("last-point-book");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (
|
|
||||||
currentPage.route === "pages/team-battle" ||
|
|
||||||
currentPage.route === "pages/melee-match"
|
|
||||||
) {
|
|
||||||
showLoader.value = true;
|
|
||||||
}
|
|
||||||
if (currentPage.route === "pages/team-battle") {
|
if (currentPage.route === "pages/team-battle") {
|
||||||
showProgress.value = true;
|
showProgress.value = true;
|
||||||
}
|
}
|
||||||
uni.$on("update-header-loading", updateLoading);
|
|
||||||
uni.$on("update-hot", updateHot);
|
uni.$on("update-hot", updateHot);
|
||||||
});
|
});
|
||||||
onBeforeUnmount(() => {
|
onBeforeUnmount(() => {
|
||||||
uni.$off("update-header-loading", updateLoading);
|
|
||||||
uni.$off("update-hot", updateHot);
|
uni.$off("update-hot", updateHot);
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
@@ -161,12 +152,6 @@ onBeforeUnmount(() => {
|
|||||||
</view>
|
</view>
|
||||||
</block>
|
</block>
|
||||||
</view>
|
</view>
|
||||||
<image
|
|
||||||
:style="{ opacity: showLoader && loading ? 0 : 0 }"
|
|
||||||
src="../static/btn-loading.png"
|
|
||||||
mode="widthFix"
|
|
||||||
class="loading"
|
|
||||||
/>
|
|
||||||
<view v-if="pointBook" class="point-book-info">
|
<view v-if="pointBook" class="point-book-info">
|
||||||
<text>{{ pointBook.bowType.name }}</text>
|
<text>{{ pointBook.bowType.name }}</text>
|
||||||
<text>{{ pointBook.distance }} 米</text>
|
<text>{{ pointBook.distance }} 米</text>
|
||||||
@@ -230,14 +215,6 @@ onBeforeUnmount(() => {
|
|||||||
font-size: 16px;
|
font-size: 16px;
|
||||||
color: #fff;
|
color: #fff;
|
||||||
}
|
}
|
||||||
.loading {
|
|
||||||
width: 20px;
|
|
||||||
height: 20px;
|
|
||||||
margin-left: 10px;
|
|
||||||
transition: all 0.3s ease;
|
|
||||||
background-blend-mode: darken;
|
|
||||||
animation: rotate 2s linear infinite;
|
|
||||||
}
|
|
||||||
.point-book-info {
|
.point-book-info {
|
||||||
color: #333;
|
color: #333;
|
||||||
position: fixed;
|
position: fixed;
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import useStore from "@/store";
|
|||||||
import { storeToRefs } from "pinia";
|
import { storeToRefs } from "pinia";
|
||||||
const { user } = storeToRefs(useStore());
|
const { user } = storeToRefs(useStore());
|
||||||
|
|
||||||
defineProps({
|
const props = defineProps({
|
||||||
player: {
|
player: {
|
||||||
type: Object,
|
type: Object,
|
||||||
default: () => ({}),
|
default: () => ({}),
|
||||||
@@ -23,7 +23,10 @@ const rowCount = new Array(6).fill(0);
|
|||||||
:style="{ borderColor: player.id === user.id ? '#FED847' : '#fff3' }"
|
:style="{ borderColor: player.id === user.id ? '#FED847' : '#fff3' }"
|
||||||
>
|
>
|
||||||
<image
|
<image
|
||||||
:style="{ opacity: scores.length === 12 ? 1 : 0 }"
|
:style="{
|
||||||
|
opacity:
|
||||||
|
(scores[0] || []).length + (scores[1] || []).length === 12 ? 1 : 0,
|
||||||
|
}"
|
||||||
src="../static/checked-green.png"
|
src="../static/checked-green.png"
|
||||||
mode="widthFix"
|
mode="widthFix"
|
||||||
/>
|
/>
|
||||||
@@ -32,20 +35,24 @@ const rowCount = new Array(6).fill(0);
|
|||||||
<view>
|
<view>
|
||||||
<view>
|
<view>
|
||||||
<view v-for="(_, index) in rowCount" :key="index">
|
<view v-for="(_, index) in rowCount" :key="index">
|
||||||
<text>{{ scores[index] ? `${scores[index].ring}环` : "-" }}</text>
|
<text>{{
|
||||||
|
scores[0] && scores[0][index] ? `${scores[0][index].ring}环` : "-"
|
||||||
|
}}</text>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
<view>
|
<view>
|
||||||
<view v-for="(_, index) in rowCount" :key="index">
|
<view v-for="(_, index) in rowCount" :key="index">
|
||||||
<text>{{
|
<text>{{
|
||||||
scores[index + 6] ? `${scores[index + 6].ring}环` : "-"
|
scores[1] && scores[1][index] ? `${scores[0][index].ring}环` : "-"
|
||||||
}}</text>
|
}}</text>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
<text
|
<text
|
||||||
>{{
|
>{{
|
||||||
scores.map((s) => s.ring).reduce((last, next) => last + next, 0)
|
scores
|
||||||
|
.map((s) => s.reduce((last, next) => last + next.ring, 0))
|
||||||
|
.reduce((last, next) => last + next, 0)
|
||||||
}}环</text
|
}}环</text
|
||||||
>
|
>
|
||||||
</view>
|
</view>
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ defineProps({
|
|||||||
type: String,
|
type: String,
|
||||||
default: "",
|
default: "",
|
||||||
},
|
},
|
||||||
scores: {
|
arrows: {
|
||||||
type: Array,
|
type: Array,
|
||||||
default: () => [],
|
default: () => [],
|
||||||
},
|
},
|
||||||
@@ -21,10 +21,6 @@ defineProps({
|
|||||||
type: Number,
|
type: Number,
|
||||||
default: 0,
|
default: 0,
|
||||||
},
|
},
|
||||||
totalRing: {
|
|
||||||
type: Number,
|
|
||||||
default: 0,
|
|
||||||
},
|
|
||||||
});
|
});
|
||||||
const rowCount = new Array(6).fill(0);
|
const rowCount = new Array(6).fill(0);
|
||||||
</script>
|
</script>
|
||||||
@@ -60,19 +56,19 @@ const rowCount = new Array(6).fill(0);
|
|||||||
<view>
|
<view>
|
||||||
<view>
|
<view>
|
||||||
<view v-for="(_, index) in rowCount" :key="index">
|
<view v-for="(_, index) in rowCount" :key="index">
|
||||||
<text>{{ scores[index] ? `${scores[index].ring}环` : "-" }}</text>
|
<text>{{ arrows[index] ? `${arrows[index].ring}环` : "-" }}</text>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
<view>
|
<view>
|
||||||
<view v-for="(_, index) in rowCount" :key="index">
|
<view v-for="(_, index) in rowCount" :key="index">
|
||||||
<text>{{
|
<text>{{
|
||||||
scores[index + 6] ? `${scores[index + 6].ring}环` : "-"
|
arrows[index + 6] ? `${arrows[index + 6].ring}环` : "-"
|
||||||
}}</text>
|
}}</text>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
<view>
|
<view>
|
||||||
<text>{{ totalRing }}环</text>
|
<text>{{ arrows.reduce((last, next) => last + next.ring, 0) }}环</text>
|
||||||
<text>积分{{ totalScore }}</text>
|
<text>积分{{ totalScore }}</text>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
|
|||||||
@@ -124,15 +124,16 @@ const seats = new Array(props.total).fill(1);
|
|||||||
right: 0;
|
right: 0;
|
||||||
} */
|
} */
|
||||||
.player-unknow {
|
.player-unknow {
|
||||||
width: 40px;
|
width: 84rpx;
|
||||||
height: 40px;
|
height: 84rpx;
|
||||||
margin: 0 24rpx;
|
margin: 0 24rpx;
|
||||||
border: 1px solid #fff3;
|
border: 1rpx solid #fff3;
|
||||||
border-radius: 50%;
|
border-radius: 50%;
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
background-color: #69686866;
|
background-color: #69686866;
|
||||||
|
box-sizing: border-box;
|
||||||
}
|
}
|
||||||
.player-unknow > image {
|
.player-unknow > image {
|
||||||
width: 40%;
|
width: 40%;
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
<script setup>
|
<script setup>
|
||||||
import { ref, watch, onMounted, onBeforeUnmount, computed } from "vue";
|
import { ref, watch, onMounted, onBeforeUnmount, computed } from "vue";
|
||||||
import audioManager from "@/audioManager";
|
import audioManager from "@/audioManager";
|
||||||
import { MESSAGETYPES } from "@/constants";
|
import { MESSAGETYPESV2 } from "@/constants";
|
||||||
import { getDirectionText } from "@/util";
|
import { getDirectionText } from "@/util";
|
||||||
|
|
||||||
import useStore from "@/store";
|
import useStore from "@/store";
|
||||||
@@ -116,62 +116,77 @@ const updateSound = () => {
|
|||||||
audioManager.setMuted(!sound.value);
|
audioManager.setMuted(!sound.value);
|
||||||
};
|
};
|
||||||
|
|
||||||
async function onReceiveMessage(messages = []) {
|
async function onReceiveMessage(msg) {
|
||||||
if (ended.value) return;
|
if (Array.isArray(msg)) return;
|
||||||
messages.forEach((msg) => {
|
if (msg.type === MESSAGETYPESV2.BattleStart) {
|
||||||
if (
|
audioManager.play("比赛开始");
|
||||||
(props.battleId && msg.constructor === MESSAGETYPES.ShootResult) ||
|
} else if (msg.type === MESSAGETYPESV2.BattleEnd) {
|
||||||
(!props.battleId && msg.constructor === MESSAGETYPES.ShootSyncMeArrowID)
|
audioManager.play("比赛结束");
|
||||||
) {
|
} else if (msg.type === MESSAGETYPESV2.ShootResult) {
|
||||||
if (props.melee && msg.userId !== user.value.id) return;
|
if (msg.shootData.playerId !== user.value.id) return;
|
||||||
if (!halfTime.value && msg.target) {
|
if (msg.shootData) {
|
||||||
let key = [];
|
let key = [];
|
||||||
key.push(msg.target.ring ? `${msg.target.ring}环` : "未上靶");
|
key.push(msg.shootData.ring ? `${msg.shootData.ring}环` : "未上靶");
|
||||||
if (!msg.target.ring)
|
if (!msg.shootData.ring)
|
||||||
key.push(`向${getDirectionText(msg.target.angle)}调整`);
|
key.push(`向${getDirectionText(msg.shootData.angle)}调整`);
|
||||||
audioManager.play(key);
|
audioManager.play(key, false);
|
||||||
}
|
|
||||||
} else if (msg.constructor === MESSAGETYPES.InvalidShot) {
|
|
||||||
if (msg.userId === user.value.id) {
|
|
||||||
uni.showToast({
|
|
||||||
title: "距离不足,无效",
|
|
||||||
icon: "none",
|
|
||||||
});
|
|
||||||
audioManager.play("射击无效");
|
|
||||||
}
|
|
||||||
} else if (msg.constructor === MESSAGETYPES.AllReady) {
|
|
||||||
audioManager.play("比赛开始");
|
|
||||||
} else if (msg.constructor === MESSAGETYPES.MeleeAllReady) {
|
|
||||||
halfTime.value = false;
|
|
||||||
audioManager.play("比赛开始");
|
|
||||||
} else if (msg.constructor === MESSAGETYPES.CurrentRoundEnded) {
|
|
||||||
currentRoundEnded.value = true;
|
|
||||||
} else if (msg.constructor === MESSAGETYPES.HalfTimeOver) {
|
|
||||||
if (props.battleId) {
|
|
||||||
halfTime.value = true;
|
|
||||||
audioManager.play("中场休息");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (wait.value !== msg.wait) {
|
|
||||||
setTimeout(() => {
|
|
||||||
wait.value = msg.wait;
|
|
||||||
if (msg.wait === 20) {
|
|
||||||
halfTime.value = true;
|
|
||||||
audioManager.play("中场休息", false);
|
|
||||||
}
|
|
||||||
if (msg.wait === 0) {
|
|
||||||
halfTime.value = false;
|
|
||||||
}
|
|
||||||
}, 200);
|
|
||||||
}
|
|
||||||
} else if (msg.constructor === MESSAGETYPES.MatchOver) {
|
|
||||||
audioManager.play("比赛结束");
|
|
||||||
} else if (msg.constructor === MESSAGETYPES.FinalShoot) {
|
|
||||||
audioManager.play("决金箭轮");
|
|
||||||
} else if (msg.constructor === MESSAGETYPES.MatchOver) {
|
|
||||||
ended.value = true;
|
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
|
// if (ended.value) return;
|
||||||
|
// messages.forEach((msg) => {
|
||||||
|
// if (
|
||||||
|
// (props.battleId && msg.constructor === MESSAGETYPES.ShootResult) ||
|
||||||
|
// (!props.battleId && msg.constructor === MESSAGETYPES.ShootSyncMeArrowID)
|
||||||
|
// ) {
|
||||||
|
// if (props.melee && msg.userId !== user.value.id) return;
|
||||||
|
// if (!halfTime.value && msg.target) {
|
||||||
|
// let key = [];
|
||||||
|
// key.push(msg.target.ring ? `${msg.target.ring}环` : "未上靶");
|
||||||
|
// if (!msg.target.ring)
|
||||||
|
// key.push(`向${getDirectionText(msg.target.angle)}调整`);
|
||||||
|
// audioManager.play(key);
|
||||||
|
// }
|
||||||
|
// } else if (msg.constructor === MESSAGETYPES.InvalidShot) {
|
||||||
|
// if (msg.userId === user.value.id) {
|
||||||
|
// uni.showToast({
|
||||||
|
// title: "距离不足,无效",
|
||||||
|
// icon: "none",
|
||||||
|
// });
|
||||||
|
// audioManager.play("射击无效");
|
||||||
|
// }
|
||||||
|
// } else if (msg.constructor === MESSAGETYPES.AllReady) {
|
||||||
|
// audioManager.play("比赛开始");
|
||||||
|
// } else if (msg.constructor === MESSAGETYPES.MeleeAllReady) {
|
||||||
|
// halfTime.value = false;
|
||||||
|
// audioManager.play("比赛开始");
|
||||||
|
// } else if (msg.constructor === MESSAGETYPES.CurrentRoundEnded) {
|
||||||
|
// currentRoundEnded.value = true;
|
||||||
|
// } else if (msg.constructor === MESSAGETYPES.HalfTimeOver) {
|
||||||
|
// if (props.battleId) {
|
||||||
|
// halfTime.value = true;
|
||||||
|
// audioManager.play("中场休息");
|
||||||
|
// return;
|
||||||
|
// }
|
||||||
|
// if (wait.value !== msg.wait) {
|
||||||
|
// setTimeout(() => {
|
||||||
|
// wait.value = msg.wait;
|
||||||
|
// if (msg.wait === 20) {
|
||||||
|
// halfTime.value = true;
|
||||||
|
// audioManager.play("中场休息", false);
|
||||||
|
// }
|
||||||
|
// if (msg.wait === 0) {
|
||||||
|
// halfTime.value = false;
|
||||||
|
// }
|
||||||
|
// }, 200);
|
||||||
|
// }
|
||||||
|
// } else if (msg.constructor === MESSAGETYPES.MatchOver) {
|
||||||
|
// audioManager.play("比赛结束");
|
||||||
|
// } else if (msg.constructor === MESSAGETYPES.FinalShoot) {
|
||||||
|
// audioManager.play("决金箭轮");
|
||||||
|
// } else if (msg.constructor === MESSAGETYPES.MatchOver) {
|
||||||
|
// ended.value = true;
|
||||||
|
// }
|
||||||
|
// });
|
||||||
}
|
}
|
||||||
|
|
||||||
const playSound = (key) => {
|
const playSound = (key) => {
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ export const MESSAGETYPESV2 = {
|
|||||||
ShootResult: 4,
|
ShootResult: 4,
|
||||||
NewRound: 5,
|
NewRound: 5,
|
||||||
BattleEnd: 6,
|
BattleEnd: 6,
|
||||||
halfRest: 7,
|
HalfRest: 7,
|
||||||
};
|
};
|
||||||
|
|
||||||
export const topThreeColors = ["#FFD947", "#D2D2D2", "#FFA515"];
|
export const topThreeColors = ["#FFD947", "#D2D2D2", "#FFA515"];
|
||||||
|
|||||||
@@ -31,10 +31,13 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"path": "pages/battle-result"
|
"path": "pages/team-battle"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"path": "pages/team-battle"
|
"path": "pages/melee-battle"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "pages/battle-result"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"path": "pages/point-book-edit"
|
"path": "pages/point-book-edit"
|
||||||
@@ -102,9 +105,6 @@
|
|||||||
{
|
{
|
||||||
"path": "pages/rank-list"
|
"path": "pages/rank-list"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"path": "pages/melee-match"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"path": "pages/match-detail"
|
"path": "pages/match-detail"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ const ifWin = ref(false);
|
|||||||
const data = ref({});
|
const data = ref({});
|
||||||
const totalPoints = ref(0);
|
const totalPoints = ref(0);
|
||||||
const rank = ref(0);
|
const rank = ref(0);
|
||||||
|
const players = ref([]);
|
||||||
|
|
||||||
function exit() {
|
function exit() {
|
||||||
if (data.value.roomId) {
|
if (data.value.roomId) {
|
||||||
@@ -30,27 +31,36 @@ function exit() {
|
|||||||
onLoad(async (options) => {
|
onLoad(async (options) => {
|
||||||
if (!options.battleId) return;
|
if (!options.battleId) return;
|
||||||
const myId = user.value.id;
|
const myId = user.value.id;
|
||||||
const result = await getBattleAPI(options.battleId || "58351917302157312");
|
const result = await getBattleAPI(options.battleId || "59090720979554304");
|
||||||
|
console.log("result", result);
|
||||||
data.value = result;
|
data.value = result;
|
||||||
if (result.winTeam) {
|
if (result.winTeam) {
|
||||||
ifWin.value = result.teams[result.winTeam].players.some(
|
ifWin.value = result.teams[result.winTeam].players.some(
|
||||||
(p) => p.id === myId
|
(p) => p.id === myId
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
if (result.way === 1) {
|
if (result.mode <= 3) {
|
||||||
audioManager.play(ifWin.value ? "胜利" : "失败");
|
audioManager.play(ifWin.value ? "胜利" : "失败");
|
||||||
} else if (result.way === 2) {
|
} else {
|
||||||
// if (data.value.battleMode === 1) {
|
players.value = result.resultList.map((item, index) => {
|
||||||
// if (rank.value <= data.value.playerStats.length * 0.3) {
|
const plist = result.teams[0] ? result.teams[0].players : [];
|
||||||
// audioManager.play("胜利");
|
const p = plist.find((p) => p.id === item.userId);
|
||||||
// }
|
if (p.id === user.value.id) {
|
||||||
// } else if (data.value.battleMode === 2) {
|
totalPoints.value = p.score;
|
||||||
// if (totalPoints.value > 0) {
|
rank.value = index + 1;
|
||||||
// audioManager.play("胜利");
|
}
|
||||||
// } else if (totalPoints.value < 0) {
|
return {
|
||||||
// audioManager.play("失败");
|
...item,
|
||||||
// }
|
rank: index + 1,
|
||||||
// }
|
name: p.name,
|
||||||
|
avatar: p.avatar || "",
|
||||||
|
};
|
||||||
|
});
|
||||||
|
if (rank.value <= players.value * 0.3) {
|
||||||
|
audioManager.play("胜利");
|
||||||
|
} else {
|
||||||
|
audioManager.play("胜利");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -71,7 +81,7 @@ const checkBowData = () => {
|
|||||||
|
|
||||||
<template>
|
<template>
|
||||||
<view class="container">
|
<view class="container">
|
||||||
<block v-if="data.way === 1">
|
<block v-if="data.mode <= 3">
|
||||||
<view class="header-team" :style="{ marginTop: '25%' }">
|
<view class="header-team" :style="{ marginTop: '25%' }">
|
||||||
<image src="../static/battle-result.png" mode="widthFix" />
|
<image src="../static/battle-result.png" mode="widthFix" />
|
||||||
<view class="header-solo" v-if="data.mode === 1">
|
<view class="header-solo" v-if="data.mode === 1">
|
||||||
@@ -161,7 +171,7 @@ const checkBowData = () => {
|
|||||||
/>
|
/>
|
||||||
</view>
|
</view>
|
||||||
</block>
|
</block>
|
||||||
<block v-if="data.way === 2">
|
<block v-else>
|
||||||
<view class="header-melee">
|
<view class="header-melee">
|
||||||
<view />
|
<view />
|
||||||
<image src="../static/battle-result.png" mode="widthFix" />
|
<image src="../static/battle-result.png" mode="widthFix" />
|
||||||
@@ -170,11 +180,11 @@ const checkBowData = () => {
|
|||||||
<view
|
<view
|
||||||
class="players"
|
class="players"
|
||||||
:style="{
|
:style="{
|
||||||
height: `${Math.max(data.playerStats.length > 5 ? '330' : '300')}px`,
|
height: `${Math.max(players.length > 5 ? '330' : '300')}px`,
|
||||||
}"
|
}"
|
||||||
>
|
>
|
||||||
<view
|
<view
|
||||||
v-for="(player, index) in data.playerStats"
|
v-for="(player, index) in players"
|
||||||
:key="index"
|
:key="index"
|
||||||
:style="{
|
:style="{
|
||||||
border: player.id === user.id ? '1px solid #B04630' : 'none',
|
border: player.id === user.id ? '1px solid #B04630' : 'none',
|
||||||
@@ -229,7 +239,7 @@ const checkBowData = () => {
|
|||||||
<text>{{ getLvlName(player.rank_lvl) }}</text>
|
<text>{{ getLvlName(player.rank_lvl) }}</text>
|
||||||
</view>
|
</view>
|
||||||
<text
|
<text
|
||||||
><text :style="{ color: '#fff' }">{{ player.totalRings }}</text>
|
><text :style="{ color: '#fff' }">{{ player.totalRing }}</text>
|
||||||
环</text
|
环</text
|
||||||
>
|
>
|
||||||
</view>
|
</view>
|
||||||
|
|||||||
@@ -35,6 +35,7 @@ const battleType = ref(0);
|
|||||||
const ready = ref(false);
|
const ready = ref(false);
|
||||||
const allReady = ref(false);
|
const allReady = ref(false);
|
||||||
const timer = ref(null);
|
const timer = ref(null);
|
||||||
|
const goBattle = ref(false);
|
||||||
|
|
||||||
async function refreshRoomData() {
|
async function refreshRoomData() {
|
||||||
if (!roomNumber.value) return;
|
if (!roomNumber.value) return;
|
||||||
@@ -147,18 +148,16 @@ async function onReceiveMessage(message) {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
} else if (message.type === MESSAGETYPESV2.AboutToStart) {
|
} else if (message.type === MESSAGETYPESV2.AboutToStart) {
|
||||||
uni.setStorageSync("blue-team", message.teams[1].players || []);
|
goBattle.value = true;
|
||||||
uni.setStorageSync("red-team", message.teams[2].players || []);
|
if (message.mode <= 3) {
|
||||||
uni.removeStorageSync("current-battle");
|
uni.setStorageSync("blue-team", message.teams[1].players || []);
|
||||||
roomNumber.value = "";
|
uni.setStorageSync("red-team", message.teams[2].players || []);
|
||||||
let params = `?gameMode=1&battleId=${message.matchId}`;
|
|
||||||
if (message.way == 1) {
|
|
||||||
uni.redirectTo({
|
uni.redirectTo({
|
||||||
url: "/pages/team-battle" + params,
|
url: "/pages/team-battle?battleId" + message.matchId,
|
||||||
});
|
});
|
||||||
} else if (message.way == 2) {
|
} else {
|
||||||
uni.redirectTo({
|
uni.redirectTo({
|
||||||
url: "/pages/melee-match" + params,
|
url: "/pages/melee-battle?battleId=" + message.matchId,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -188,6 +187,7 @@ onShareAppMessage(() => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
onShow(() => {
|
onShow(() => {
|
||||||
|
goBattle.value = false;
|
||||||
refreshRoomData();
|
refreshRoomData();
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -207,7 +207,7 @@ onBeforeUnmount(() => {
|
|||||||
keepScreenOn: false,
|
keepScreenOn: false,
|
||||||
});
|
});
|
||||||
uni.$off("socket-inbox", onReceiveMessage);
|
uni.$off("socket-inbox", onReceiveMessage);
|
||||||
if (roomNumber.value) exitRoomAPI(roomNumber.value);
|
if (!goBattle.value) exitRoomAPI(roomNumber.value);
|
||||||
if (timer.value) clearInterval(timer.value);
|
if (timer.value) clearInterval(timer.value);
|
||||||
timer.value = null;
|
timer.value = null;
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -7,21 +7,39 @@ import Avatar from "@/components/Avatar.vue";
|
|||||||
import PlayerScore2 from "@/components/PlayerScore2.vue";
|
import PlayerScore2 from "@/components/PlayerScore2.vue";
|
||||||
import { getBattleAPI } from "@/apis";
|
import { getBattleAPI } from "@/apis";
|
||||||
|
|
||||||
const blueTeam = ref([]);
|
|
||||||
const redTeam = ref([]);
|
|
||||||
const roundsData = ref([]);
|
|
||||||
const goldenRoundsData = ref([]);
|
|
||||||
const battleId = ref("");
|
const battleId = ref("");
|
||||||
const data = ref({
|
const data = ref({
|
||||||
teams: [],
|
teams: [],
|
||||||
rounds: [],
|
rounds: [],
|
||||||
});
|
});
|
||||||
|
const players = ref([]);
|
||||||
|
|
||||||
onLoad(async (options) => {
|
onLoad(async (options) => {
|
||||||
if (!options.id) return;
|
if (!options.id) return;
|
||||||
battleId.value = options.id || "57943107462893568";
|
battleId.value = options.id || "59090720979554304";
|
||||||
const result = await getBattleAPI(battleId.value);
|
const result = await getBattleAPI(battleId.value);
|
||||||
data.value = result;
|
data.value = result;
|
||||||
|
if (result.mode > 3) {
|
||||||
|
players.value = result.resultList.map((item, index) => {
|
||||||
|
const plist = result.teams[0] ? result.teams[0].players : [];
|
||||||
|
const p = plist.find((p) => p.id === item.userId);
|
||||||
|
const arrows = new Array(12);
|
||||||
|
result.rounds.forEach((r, index) => {
|
||||||
|
if (r.shoots[item.userId]) {
|
||||||
|
r.shoots[item.userId].forEach((s, index2) => {
|
||||||
|
arrows[index2 + index * 6] = s;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return {
|
||||||
|
...item,
|
||||||
|
rank: index + 1,
|
||||||
|
name: p.name,
|
||||||
|
avatar: p.avatar || "",
|
||||||
|
arrows,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
const checkBowData = (selected) => {
|
const checkBowData = (selected) => {
|
||||||
@@ -44,10 +62,10 @@ const checkBowData = (selected) => {
|
|||||||
:winner="data.winTeam"
|
:winner="data.winTeam"
|
||||||
:blueTeam="data.teams[1] ? data.teams[1].players : []"
|
:blueTeam="data.teams[1] ? data.teams[1].players : []"
|
||||||
:redTeam="data.teams[2] ? data.teams[2].players : []"
|
:redTeam="data.teams[2] ? data.teams[2].players : []"
|
||||||
:players="data.players"
|
:players="players"
|
||||||
/>
|
/>
|
||||||
<view
|
<view
|
||||||
v-if="data.mode > 3"
|
v-if="data.mode >= 3"
|
||||||
class="score-header"
|
class="score-header"
|
||||||
:style="{ border: 'none', padding: '5px 15px' }"
|
:style="{ border: 'none', padding: '5px 15px' }"
|
||||||
>
|
>
|
||||||
@@ -58,17 +76,17 @@ const checkBowData = (selected) => {
|
|||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
<PlayerScore2
|
<PlayerScore2
|
||||||
v-if="data.mode > 3"
|
v-if="data.mode >= 3"
|
||||||
v-for="(player, index) in data.players"
|
v-for="(player, index) in players"
|
||||||
:key="index"
|
:key="index"
|
||||||
:name="player.name"
|
:name="player.name"
|
||||||
:avatar="player.avatar"
|
:avatar="player.avatar"
|
||||||
:scores="player.arrowHistory"
|
:arrows="player.arrows"
|
||||||
:totalScore="player.totalScore"
|
:totalScore="player.totalScore"
|
||||||
:totalRing="player.totalRings"
|
|
||||||
:rank="index + 1"
|
:rank="index + 1"
|
||||||
/>
|
/>
|
||||||
<view
|
<view
|
||||||
|
v-if="data.mode <= 3"
|
||||||
v-for="(round, index) in data.rounds"
|
v-for="(round, index) in data.rounds"
|
||||||
:key="index"
|
:key="index"
|
||||||
:style="{ marginBottom: '5px' }"
|
:style="{ marginBottom: '5px' }"
|
||||||
|
|||||||
@@ -29,14 +29,13 @@ async function onReceiveMessage(messages = []) {
|
|||||||
...msg.groupUserStatus.blueTeam,
|
...msg.groupUserStatus.blueTeam,
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
uni.removeStorageSync("current-battle");
|
|
||||||
if (gameType.value == 1) {
|
if (gameType.value == 1) {
|
||||||
uni.redirectTo({
|
uni.redirectTo({
|
||||||
url: `/pages/team-battle?battleId=${msg.id}&gameMode=2`,
|
url: `/pages/team-battle?battleId=${msg.id}&gameMode=2`,
|
||||||
});
|
});
|
||||||
} else if (gameType.value == 2) {
|
} else if (gameType.value == 2) {
|
||||||
uni.redirectTo({
|
uni.redirectTo({
|
||||||
url: `/pages/melee-match?battleId=${msg.id}&gameMode=2`,
|
url: `/pages/melee-battle?battleId=${msg.id}&gameMode=2`,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
205
src/pages/melee-battle.vue
Normal file
205
src/pages/melee-battle.vue
Normal file
@@ -0,0 +1,205 @@
|
|||||||
|
<script setup>
|
||||||
|
import { ref, onMounted, onBeforeUnmount } from "vue";
|
||||||
|
import { onLoad, onShow, onHide } from "@dcloudio/uni-app";
|
||||||
|
import Container from "@/components/Container.vue";
|
||||||
|
import BowTarget from "@/components/BowTarget.vue";
|
||||||
|
import ShootProgress from "@/components/ShootProgress.vue";
|
||||||
|
import BattleHeader from "@/components/BattleHeader.vue";
|
||||||
|
import PlayerScore from "@/components/PlayerScore.vue";
|
||||||
|
import SButton from "@/components/SButton.vue";
|
||||||
|
import Avatar from "@/components/Avatar.vue";
|
||||||
|
import ScreenHint from "@/components/ScreenHint.vue";
|
||||||
|
import TestDistance from "@/components/TestDistance.vue";
|
||||||
|
import audioManager from "@/audioManager";
|
||||||
|
import { getBattleAPI, laserCloseAPI } from "@/apis";
|
||||||
|
import { isGameEnded } from "@/util";
|
||||||
|
import { MESSAGETYPESV2 } from "@/constants";
|
||||||
|
import useStore from "@/store";
|
||||||
|
import { storeToRefs } from "pinia";
|
||||||
|
const store = useStore();
|
||||||
|
const { user } = storeToRefs(store);
|
||||||
|
const title = ref("");
|
||||||
|
const start = ref(null);
|
||||||
|
const battleId = ref("");
|
||||||
|
const currentRound = ref(1);
|
||||||
|
const tips = ref("即将开始...");
|
||||||
|
const players = ref([]);
|
||||||
|
const playersSorted = ref([]);
|
||||||
|
const playersScores = ref([]);
|
||||||
|
const halfTimeTip = ref(false);
|
||||||
|
const halfRest = ref(false);
|
||||||
|
|
||||||
|
function recoverData(battleInfo, { force = false } = {}) {
|
||||||
|
console.log("battleInfo", battleInfo);
|
||||||
|
if (battleInfo.way === 1) title.value = "好友约战 - 大乱斗";
|
||||||
|
if (battleInfo.way === 2) title.value = "排位赛 - 大乱斗";
|
||||||
|
players.value = battleInfo.teams[0].players;
|
||||||
|
start.value = battleInfo.status !== 0;
|
||||||
|
if (battleInfo.status === 0) {
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
tips.value =
|
||||||
|
(battleInfo.rounds.length !== 2 ? "上" : "下") + "半场:请先射6箭";
|
||||||
|
playersScores.value = battleInfo.rounds.map((r) => ({ ...r.shoots }));
|
||||||
|
const totals = {};
|
||||||
|
players.value.forEach((p) => {
|
||||||
|
const total = playersScores.value.reduce((acc, round) => {
|
||||||
|
const arr = round[p.id] || [];
|
||||||
|
return acc + arr.length;
|
||||||
|
}, 0);
|
||||||
|
totals[p.id] = total;
|
||||||
|
});
|
||||||
|
playersSorted.value = players.value.slice().sort((a, b) => {
|
||||||
|
return totals[b.id] - totals[a.id];
|
||||||
|
});
|
||||||
|
if (battleInfo.status === 3) {
|
||||||
|
halfTimeTip.value = true;
|
||||||
|
halfRest.value = true;
|
||||||
|
tips.value = "准备下半场";
|
||||||
|
// 剩余休息时间
|
||||||
|
// const remain = (Date.now() - battleInfo.timeoutTime) / 1000;
|
||||||
|
setTimeout(() => {
|
||||||
|
uni.$emit("update-remain", 0);
|
||||||
|
}, 200);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (force) {
|
||||||
|
const remain = (Date.now() - battleInfo.current.startTime) / 1000;
|
||||||
|
console.log(
|
||||||
|
`当前轮已进行${remain}秒,${Date.now()},${
|
||||||
|
battleInfo.current.startTimeText
|
||||||
|
}`
|
||||||
|
);
|
||||||
|
if (remain > 0 && remain < 90) {
|
||||||
|
setTimeout(() => {
|
||||||
|
uni.$emit("update-remain", 90 - remain - 0.2);
|
||||||
|
}, 200);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
uni.$emit("update-remain", battleInfo.readyTime);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onLoad(async (options) => {
|
||||||
|
if (options.battleId) battleId.value = options.battleId;
|
||||||
|
uni.enableAlertBeforeUnload({
|
||||||
|
message: "离开比赛可能导致比赛失败,是否继续?",
|
||||||
|
success: (res) => {
|
||||||
|
console.log("已启用离开提示");
|
||||||
|
},
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
async function onReceiveMessage(msg) {
|
||||||
|
if (Array.isArray(msg)) return;
|
||||||
|
if (msg.type === MESSAGETYPESV2.BattleStart) {
|
||||||
|
halfTimeTip.value = false;
|
||||||
|
halfRest.value = false;
|
||||||
|
recoverData(msg);
|
||||||
|
} else if (msg.type === MESSAGETYPESV2.ShootResult) {
|
||||||
|
recoverData(msg);
|
||||||
|
} else if (msg.type === MESSAGETYPESV2.HalfRest) {
|
||||||
|
halfTimeTip.value = true;
|
||||||
|
halfRest.value = true;
|
||||||
|
tips.value = "准备下半场";
|
||||||
|
} else if (msg.type === MESSAGETYPESV2.BattleEnd) {
|
||||||
|
uni.redirectTo({
|
||||||
|
url: "/pages/battle-result?battleId=" + msg.matchId,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
onMounted(async () => {
|
||||||
|
uni.setKeepScreenOn({
|
||||||
|
keepScreenOn: true,
|
||||||
|
});
|
||||||
|
uni.$on("socket-inbox", onReceiveMessage);
|
||||||
|
await laserCloseAPI();
|
||||||
|
});
|
||||||
|
onBeforeUnmount(() => {
|
||||||
|
uni.setKeepScreenOn({
|
||||||
|
keepScreenOn: false,
|
||||||
|
});
|
||||||
|
uni.$off("socket-inbox", onReceiveMessage);
|
||||||
|
audioManager.stopAll();
|
||||||
|
});
|
||||||
|
|
||||||
|
onShow(async () => {
|
||||||
|
if (battleId.value) {
|
||||||
|
const result = await getBattleAPI(battleId.value);
|
||||||
|
if (result.status === 2) {
|
||||||
|
uni.showToast({
|
||||||
|
title: "比赛已结束",
|
||||||
|
icon: "none",
|
||||||
|
});
|
||||||
|
uni.navigateBack({
|
||||||
|
delta: 2,
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
recoverData(result, { force: true });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<Container :title="title" :bgType="1">
|
||||||
|
<view class="container">
|
||||||
|
<BattleHeader v-if="!start" :players="players" />
|
||||||
|
<TestDistance v-if="start === false" :guide="false" :isBattle="true" />
|
||||||
|
<ShootProgress
|
||||||
|
:show="start"
|
||||||
|
:start="start && !halfRest"
|
||||||
|
:tips="tips"
|
||||||
|
:total="90"
|
||||||
|
:melee="true"
|
||||||
|
:battleId="battleId"
|
||||||
|
/>
|
||||||
|
<view v-if="start" class="user-row">
|
||||||
|
<Avatar :src="user.avatar" :size="35" />
|
||||||
|
<BowPower />
|
||||||
|
</view>
|
||||||
|
<BowTarget
|
||||||
|
v-if="start"
|
||||||
|
:currentRound="
|
||||||
|
playersScores.map((s) => s[user.id].length).reduce((a, b) => a + b, 0)
|
||||||
|
"
|
||||||
|
:totalRound="12"
|
||||||
|
:scores="playersScores.map((r) => r[user.id]).flat()"
|
||||||
|
:stop="halfRest"
|
||||||
|
/>
|
||||||
|
<view :style="{ paddingBottom: '20px' }">
|
||||||
|
<PlayerScore
|
||||||
|
v-if="start"
|
||||||
|
v-for="(player, index) in playersSorted"
|
||||||
|
:key="index"
|
||||||
|
:player="player"
|
||||||
|
:scores="playersScores.map((s) => s[player.id])"
|
||||||
|
/>
|
||||||
|
</view>
|
||||||
|
<ScreenHint
|
||||||
|
:show="halfTimeTip"
|
||||||
|
mode="small"
|
||||||
|
:onClose="() => (halfTimeTip = false)"
|
||||||
|
>
|
||||||
|
<view class="half-time-tip">
|
||||||
|
<text>上半场结束,休息一下吧:)</text>
|
||||||
|
<text>20秒后开始下半场</text>
|
||||||
|
</view>
|
||||||
|
</ScreenHint>
|
||||||
|
</view>
|
||||||
|
</Container>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.container {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -4,28 +4,39 @@ import { onLoad } from "@dcloudio/uni-app";
|
|||||||
import Container from "@/components/Container.vue";
|
import Container from "@/components/Container.vue";
|
||||||
import BowTarget from "@/components/BowTarget.vue";
|
import BowTarget from "@/components/BowTarget.vue";
|
||||||
import Avatar from "@/components/Avatar.vue";
|
import Avatar from "@/components/Avatar.vue";
|
||||||
import { getGameAPI } from "@/apis";
|
import { getBattleAPI } from "@/apis";
|
||||||
import useStore from "@/store";
|
import useStore from "@/store";
|
||||||
import { storeToRefs } from "pinia";
|
import { storeToRefs } from "pinia";
|
||||||
const store = useStore();
|
const { user } = storeToRefs(useStore());
|
||||||
const { user } = storeToRefs(store);
|
const currentUser = ref({
|
||||||
const scores = ref([]);
|
arrows: [],
|
||||||
const currentUser = ref({});
|
});
|
||||||
const data = ref({});
|
const players = ref([]);
|
||||||
const onSelect = (userId) => {
|
|
||||||
const user = data.value.players.find((p) => p.playerId === userId);
|
|
||||||
currentUser.value = user;
|
|
||||||
if (user && user.arrowHistory) {
|
|
||||||
scores.value = user.arrowHistory;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
onLoad(async (options) => {
|
onLoad(async (options) => {
|
||||||
if (options.battleId) {
|
if (!options.id) return;
|
||||||
const result = await getGameAPI(options.battleId);
|
const result = await getBattleAPI(options.battleId || "59090720979554304");
|
||||||
data.value = result;
|
players.value = result.resultList.map((item, index) => {
|
||||||
if (result.players && result.players[0]) {
|
const plist = result.teams[0] ? result.teams[0].players : [];
|
||||||
onSelect(result.players[0].playerId);
|
const p = plist.find((p) => p.id === item.userId);
|
||||||
}
|
const arrows = new Array(12);
|
||||||
|
result.rounds.forEach((r, index) => {
|
||||||
|
if (r.shoots[item.userId]) {
|
||||||
|
r.shoots[item.userId].forEach((s, index2) => {
|
||||||
|
arrows[index2 + index * 6] = s;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return {
|
||||||
|
...item,
|
||||||
|
rank: index + 1,
|
||||||
|
name: p.name,
|
||||||
|
avatar: p.avatar || "",
|
||||||
|
arrows,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
if (players.value[0]) {
|
||||||
|
currentUser.value = players.value[0];
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
@@ -33,22 +44,26 @@ onLoad(async (options) => {
|
|||||||
<template>
|
<template>
|
||||||
<Container title="靶纸">
|
<Container title="靶纸">
|
||||||
<view class="container">
|
<view class="container">
|
||||||
<image src="../static/battle-header-melee.png" mode="widthFix" />
|
<image
|
||||||
<view class="players" v-if="data.players">
|
src="../static/battle-header-melee.png"
|
||||||
|
mode="widthFix"
|
||||||
|
:style="{ top: '-50rpx' }"
|
||||||
|
/>
|
||||||
|
<view class="players">
|
||||||
<view
|
<view
|
||||||
v-for="(player, index) in data.players"
|
v-for="(player, index) in players"
|
||||||
:key="index"
|
:key="index"
|
||||||
:style="{
|
:style="{
|
||||||
width: `${Math.max(100 / data.players.length, 18)}vw`,
|
width: `${Math.max(100 / players.length, 18)}vw`,
|
||||||
color: player.playerId === currentUser.playerId ? '#000' : '#fff9',
|
color: player.userId === currentUser.userId ? '#000' : '#fff9',
|
||||||
}"
|
}"
|
||||||
@click="() => onSelect(player.playerId)"
|
@click="currentUser = player"
|
||||||
>
|
>
|
||||||
<image
|
<image
|
||||||
v-if="player.playerId === currentUser.playerId"
|
v-if="player.userId === currentUser.userId"
|
||||||
src="../static/player-bg2.png"
|
src="../static/player-bg2.png"
|
||||||
:style="{
|
:style="{
|
||||||
width: `${Math.max(100 / data.players.length, 18)}vw`,
|
width: `${Math.max(100 / players.length, 18)}vw`,
|
||||||
}"
|
}"
|
||||||
class="player-bg"
|
class="player-bg"
|
||||||
/>
|
/>
|
||||||
@@ -57,18 +72,20 @@ onLoad(async (options) => {
|
|||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
<view :style="{ marginTop: '10px' }">
|
<view :style="{ marginTop: '10px' }">
|
||||||
<BowTarget :scores="scores" />
|
<BowTarget :scores="currentUser.arrows" />
|
||||||
</view>
|
</view>
|
||||||
<view class="score-text"
|
<view class="score-text"
|
||||||
><text :style="{ color: '#fed847' }">{{ scores.length }}</text
|
><text :style="{ color: '#fed847' }">{{
|
||||||
|
currentUser.arrows.length
|
||||||
|
}}</text
|
||||||
>支箭,共<text :style="{ color: '#fed847' }">{{
|
>支箭,共<text :style="{ color: '#fed847' }">{{
|
||||||
scores.reduce((last, next) => last + next.ring, 0)
|
currentUser.arrows.reduce((last, next) => last + next.ring, 0)
|
||||||
}}</text
|
}}</text
|
||||||
>环</view
|
>环</view
|
||||||
>
|
>
|
||||||
<view class="score-row">
|
<view class="score-row" v-if="currentUser.arrows">
|
||||||
<view
|
<view
|
||||||
v-for="(score, index) in scores"
|
v-for="(score, index) in currentUser.arrows"
|
||||||
:key="index"
|
:key="index"
|
||||||
class="score-item"
|
class="score-item"
|
||||||
:style="{ width: '13vw', height: '13vw' }"
|
:style="{ width: '13vw', height: '13vw' }"
|
||||||
@@ -97,7 +114,7 @@ onLoad(async (options) => {
|
|||||||
display: flex;
|
display: flex;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
overflow-x: auto;
|
overflow-x: auto;
|
||||||
margin-top: 25px;
|
margin-top: 50rpx;
|
||||||
}
|
}
|
||||||
.players::-webkit-scrollbar {
|
.players::-webkit-scrollbar {
|
||||||
width: 0;
|
width: 0;
|
||||||
|
|||||||
@@ -1,248 +0,0 @@
|
|||||||
<script setup>
|
|
||||||
import { ref, watch, onMounted, onBeforeUnmount } from "vue";
|
|
||||||
import { onLoad, onShow, onHide } from "@dcloudio/uni-app";
|
|
||||||
import Container from "@/components/Container.vue";
|
|
||||||
import BowTarget from "@/components/BowTarget.vue";
|
|
||||||
import ShootProgress from "@/components/ShootProgress.vue";
|
|
||||||
import BattleHeader from "@/components/BattleHeader.vue";
|
|
||||||
import PlayerScore from "@/components/PlayerScore.vue";
|
|
||||||
import SButton from "@/components/SButton.vue";
|
|
||||||
import Avatar from "@/components/Avatar.vue";
|
|
||||||
import ScreenHint from "@/components/ScreenHint.vue";
|
|
||||||
import TestDistance from "@/components/TestDistance.vue";
|
|
||||||
import audioManager from "@/audioManager";
|
|
||||||
import { getCurrentGameAPI, laserCloseAPI } from "@/apis";
|
|
||||||
import { isGameEnded } from "@/util";
|
|
||||||
import { MESSAGETYPES } from "@/constants";
|
|
||||||
import useStore from "@/store";
|
|
||||||
import { storeToRefs } from "pinia";
|
|
||||||
const store = useStore();
|
|
||||||
const { user } = storeToRefs(store);
|
|
||||||
const title = ref("大乱斗");
|
|
||||||
const start = ref(false);
|
|
||||||
const startCount = ref(true);
|
|
||||||
const battleId = ref("");
|
|
||||||
const currentRound = ref(1);
|
|
||||||
const scores = ref([]);
|
|
||||||
const tips = ref("即将开始...");
|
|
||||||
const players = ref([]);
|
|
||||||
const playersSorted = ref([]);
|
|
||||||
const playersScores = ref({});
|
|
||||||
const halfTimeTip = ref(false);
|
|
||||||
const isEnded = ref(false);
|
|
||||||
|
|
||||||
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;
|
|
||||||
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];
|
|
||||||
});
|
|
||||||
const remain = Date.now() / 1000 - battleInfo.startTime;
|
|
||||||
console.log(`当前局已进行${remain}秒`);
|
|
||||||
if (battleInfo.status === 0) {
|
|
||||||
if (remain > 0) {
|
|
||||||
setTimeout(() => {
|
|
||||||
uni.$emit("update-timer", 15 - remain);
|
|
||||||
}, 200);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
start.value = true;
|
|
||||||
}
|
|
||||||
if (battleInfo.status === 2) {
|
|
||||||
const elapsedTime = (Date.now() - Date.parse(battleInfo.createdAt)) / 1000;
|
|
||||||
console.log("elapsedTime:", elapsedTime);
|
|
||||||
startCount.value = true;
|
|
||||||
// 这里的开始时间不是游戏开始时间,而是上半场或者下半场或者中场的开始时间,还要根据状态来判断
|
|
||||||
tips.value = battleInfo.halfGame
|
|
||||||
? "下半场:请再射6箭"
|
|
||||||
: "上半场:请先射6箭";
|
|
||||||
setTimeout(() => {
|
|
||||||
uni.$emit("update-remain", 90 - remain);
|
|
||||||
}, 200);
|
|
||||||
} else if (battleInfo.status === 9) {
|
|
||||||
startCount.value = false;
|
|
||||||
tips.value = "准备下半场";
|
|
||||||
setTimeout(() => {
|
|
||||||
uni.$emit("update-remain", 0);
|
|
||||||
}, 200);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
onLoad(async (options) => {
|
|
||||||
if (options.gameMode == 1) title.value = "好友约战 - 大乱斗";
|
|
||||||
if (options.gameMode == 2) title.value = "排位赛 - 大乱斗";
|
|
||||||
if (options.battleId) {
|
|
||||||
battleId.value = options.battleId;
|
|
||||||
const players = uni.getStorageSync("melee-players");
|
|
||||||
if (players) {
|
|
||||||
players.value = players;
|
|
||||||
players.value.forEach((p) => {
|
|
||||||
playersScores.value[p.id] = [];
|
|
||||||
});
|
|
||||||
}
|
|
||||||
const battleInfo = uni.getStorageSync("current-battle");
|
|
||||||
if (battleInfo) {
|
|
||||||
recoverData(battleInfo);
|
|
||||||
setTimeout(getCurrentGameAPI, 2000);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
uni.enableAlertBeforeUnload({
|
|
||||||
message: "离开比赛可能导致比赛失败,是否继续?",
|
|
||||||
success: (res) => {
|
|
||||||
console.log("已启用离开提示");
|
|
||||||
},
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
async function onReceiveMessage(messages = []) {
|
|
||||||
messages.forEach((msg) => {
|
|
||||||
if (msg.id !== battleId.value) return;
|
|
||||||
if (msg.constructor === MESSAGETYPES.MeleeAllReady) {
|
|
||||||
start.value = true;
|
|
||||||
startCount.value = true;
|
|
||||||
tips.value = scores.value.length
|
|
||||||
? "下半场:请再射6箭"
|
|
||||||
: "上半场:请先射6箭";
|
|
||||||
halfTimeTip.value = false;
|
|
||||||
}
|
|
||||||
if (msg.constructor === MESSAGETYPES.ShootResult) {
|
|
||||||
if (!start.value) getCurrentGameAPI();
|
|
||||||
if (msg.userId === user.value.id) {
|
|
||||||
scores.value.push({ ...msg.target });
|
|
||||||
}
|
|
||||||
playersScores.value[msg.userId].push({ ...msg.target });
|
|
||||||
}
|
|
||||||
if (msg.constructor === MESSAGETYPES.HalfTimeOver) {
|
|
||||||
uni.$emit("update-remain", 0);
|
|
||||||
[...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) {
|
|
||||||
isEnded.value = true;
|
|
||||||
uni.setStorageSync("last-battle", msg.endStatus);
|
|
||||||
setTimeout(() => {
|
|
||||||
uni.redirectTo({
|
|
||||||
url: "/pages/battle-result",
|
|
||||||
});
|
|
||||||
}, 1000);
|
|
||||||
}
|
|
||||||
if (msg.constructor === MESSAGETYPES.BackToGame) {
|
|
||||||
uni.$emit("update-header-loading", false);
|
|
||||||
if (msg.battleInfo) recoverData(msg.battleInfo);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
onMounted(async () => {
|
|
||||||
uni.setKeepScreenOn({
|
|
||||||
keepScreenOn: true,
|
|
||||||
});
|
|
||||||
uni.$on("socket-inbox", onReceiveMessage);
|
|
||||||
await laserCloseAPI();
|
|
||||||
});
|
|
||||||
onBeforeUnmount(() => {
|
|
||||||
uni.setKeepScreenOn({
|
|
||||||
keepScreenOn: false,
|
|
||||||
});
|
|
||||||
uni.$off("socket-inbox", onReceiveMessage);
|
|
||||||
audioManager.stopAll();
|
|
||||||
});
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
onHide(() => {
|
|
||||||
if (refreshTimer.value) clearInterval(refreshTimer.value);
|
|
||||||
uni.setStorageSync("last-awake-time", Date.now());
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<template>
|
|
||||||
<Container :title="title" :bgType="1">
|
|
||||||
<view class="container">
|
|
||||||
<BattleHeader v-if="!start" :players="players" />
|
|
||||||
<TestDistance v-if="!start" :guide="false" :isBattle="true" />
|
|
||||||
<ShootProgress
|
|
||||||
:show="start"
|
|
||||||
:start="start && startCount"
|
|
||||||
:tips="tips"
|
|
||||||
:total="90"
|
|
||||||
:melee="true"
|
|
||||||
:battleId="battleId"
|
|
||||||
/>
|
|
||||||
<view v-if="start" class="user-row">
|
|
||||||
<Avatar :src="user.avatar" :size="35" />
|
|
||||||
<BowPower />
|
|
||||||
</view>
|
|
||||||
<BowTarget
|
|
||||||
v-if="start"
|
|
||||||
:currentRound="scores.length"
|
|
||||||
:totalRound="12"
|
|
||||||
:scores="scores"
|
|
||||||
:stop="!startCount"
|
|
||||||
/>
|
|
||||||
<view :style="{ paddingBottom: '20px' }">
|
|
||||||
<PlayerScore
|
|
||||||
v-if="start"
|
|
||||||
v-for="(player, index) in playersSorted"
|
|
||||||
:key="index"
|
|
||||||
:player="player"
|
|
||||||
:scores="playersScores[player.id] || []"
|
|
||||||
/>
|
|
||||||
</view>
|
|
||||||
<ScreenHint
|
|
||||||
:show="halfTimeTip"
|
|
||||||
mode="small"
|
|
||||||
:onClose="() => (halfTimeTip = false)"
|
|
||||||
>
|
|
||||||
<view class="half-time-tip">
|
|
||||||
<text>上半场结束,休息一下吧:)</text>
|
|
||||||
<text>20秒后开始下半场</text>
|
|
||||||
</view>
|
|
||||||
</ScreenHint>
|
|
||||||
</view>
|
|
||||||
</Container>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<style scoped>
|
|
||||||
.container {
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
@@ -12,7 +12,7 @@ import RoundEndTip from "@/components/RoundEndTip.vue";
|
|||||||
import TestDistance from "@/components/TestDistance.vue";
|
import TestDistance from "@/components/TestDistance.vue";
|
||||||
import TeamAvatars from "@/components/TeamAvatars.vue";
|
import TeamAvatars from "@/components/TeamAvatars.vue";
|
||||||
import ShootProgress2 from "@/components/ShootProgress2.vue";
|
import ShootProgress2 from "@/components/ShootProgress2.vue";
|
||||||
import { getCurrentGameAPI, laserCloseAPI, getBattleAPI } from "@/apis";
|
import { laserCloseAPI, getBattleAPI } from "@/apis";
|
||||||
import { isGameEnded, formatTimestamp } from "@/util";
|
import { isGameEnded, formatTimestamp } from "@/util";
|
||||||
import { MESSAGETYPES, MESSAGETYPESV2, roundsName } from "@/constants";
|
import { MESSAGETYPES, MESSAGETYPESV2, roundsName } from "@/constants";
|
||||||
import audioManager from "@/audioManager";
|
import audioManager from "@/audioManager";
|
||||||
@@ -43,8 +43,8 @@ const recoverData = (battleInfo, { force = false, arrowOnly = false } = {}) => {
|
|||||||
battleId.value = battleInfo.matchId;
|
battleId.value = battleInfo.matchId;
|
||||||
blueTeam.value = battleInfo.teams[1].players || [];
|
blueTeam.value = battleInfo.teams[1].players || [];
|
||||||
redTeam.value = battleInfo.teams[2].players || [];
|
redTeam.value = battleInfo.teams[2].players || [];
|
||||||
|
start.value = battleInfo.status !== 0;
|
||||||
if (battleInfo.status === 0) {
|
if (battleInfo.status === 0) {
|
||||||
start.value = false;
|
|
||||||
const readyRemain = (Date.now() - battleInfo.createTime) / 1000;
|
const readyRemain = (Date.now() - battleInfo.createTime) / 1000;
|
||||||
console.log(`对局已进行${readyRemain}秒`);
|
console.log(`对局已进行${readyRemain}秒`);
|
||||||
if (readyRemain > 0 && readyRemain < 15) {
|
if (readyRemain > 0 && readyRemain < 15) {
|
||||||
@@ -55,7 +55,6 @@ const recoverData = (battleInfo, { force = false, arrowOnly = false } = {}) => {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (!arrowOnly) {
|
if (!arrowOnly) {
|
||||||
start.value = true;
|
|
||||||
currentShooterId.value = battleInfo.current.playerId;
|
currentShooterId.value = battleInfo.current.playerId;
|
||||||
const redPlayer = battleInfo.teams[2].players.find(
|
const redPlayer = battleInfo.teams[2].players.find(
|
||||||
(item) => item.id === battleInfo.current.playerId
|
(item) => item.id === battleInfo.current.playerId
|
||||||
|
|||||||
@@ -56,31 +56,7 @@ function createWebSocket(token, onMessage) {
|
|||||||
const msg = data.updates[0];
|
const msg = data.updates[0];
|
||||||
if (msg) {
|
if (msg) {
|
||||||
console.log("收到消息:", getMessageTypeName(msg.constructor), msg);
|
console.log("收到消息:", getMessageTypeName(msg.constructor), msg);
|
||||||
if (msg.constructor === MESSAGETYPES.BackToGame) {
|
if (msg.constructor === MESSAGETYPES.RankUpdate) {
|
||||||
const pages = getCurrentPages();
|
|
||||||
const currentPage = pages[pages.length - 1];
|
|
||||||
if (
|
|
||||||
currentPage.route === "pages/battle-room" ||
|
|
||||||
currentPage.route === "pages/team-battle" ||
|
|
||||||
currentPage.route === "pages/melee-match"
|
|
||||||
) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const { battleInfo } = msg;
|
|
||||||
uni.setStorageSync("current-battle", battleInfo);
|
|
||||||
// console.log("----battleInfo", battleInfo);
|
|
||||||
if (battleInfo.config.mode === 1) {
|
|
||||||
uni.navigateTo({
|
|
||||||
url: `/pages/team-battle?battleId=${battleInfo.id}&gameMode=${battleInfo.config.battleMode}`,
|
|
||||||
});
|
|
||||||
} else if (battleInfo.config.mode === 2) {
|
|
||||||
uni.navigateTo({
|
|
||||||
url: `/pages/melee-match?battleId=${battleInfo.id}&gameMode=${battleInfo.config.battleMode}`,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
} else if (msg.constructor === MESSAGETYPES.MatchOver) {
|
|
||||||
uni.$emit("game-over");
|
|
||||||
} else if (msg.constructor === MESSAGETYPES.RankUpdate) {
|
|
||||||
uni.setStorageSync("latestRank", msg.lvl);
|
uni.setStorageSync("latestRank", msg.lvl);
|
||||||
} else if (msg.constructor === MESSAGETYPES.LvlUpdate) {
|
} else if (msg.constructor === MESSAGETYPES.LvlUpdate) {
|
||||||
uni.setStorageSync("latestLvl", msg.lvl);
|
uni.setStorageSync("latestLvl", msg.lvl);
|
||||||
|
|||||||
Reference in New Issue
Block a user