158 lines
4.8 KiB
Vue
158 lines
4.8 KiB
Vue
<script setup>
|
|
import { ref, onMounted, onUnmounted } from "vue";
|
|
import { onLoad } from "@dcloudio/uni-app";
|
|
import Container from "@/components/Container.vue";
|
|
import BowTarget from "@/components/BowTarget.vue";
|
|
import ShootProgress from "@/components/ShootProgress.vue";
|
|
import Guide from "@/components/Guide.vue";
|
|
import BattleHeader from "@/components/BattleHeader.vue";
|
|
import Timer from "@/components/Timer.vue";
|
|
import PlayerScore from "@/components/PlayerScore.vue";
|
|
import SButton from "@/components/SButton.vue";
|
|
import { matchGameAPI, readyGameAPI } from "@/apis";
|
|
import { MESSAGETYPES } from "@/constants";
|
|
import useStore from "@/store";
|
|
import { storeToRefs } from "pinia";
|
|
const store = useStore();
|
|
const { user } = storeToRefs(store);
|
|
const gameType = ref(0);
|
|
const teamSize = ref(0);
|
|
const matching = ref(false);
|
|
const start = ref(false);
|
|
const battleId = ref("");
|
|
const currentRound = ref(1);
|
|
const totalRounds = ref(0);
|
|
const power = ref(0);
|
|
const scores = ref([]);
|
|
const tips = ref("即将开始...");
|
|
const timerSeq = ref(0);
|
|
const players = ref([]);
|
|
const playersScores = ref({});
|
|
|
|
onLoad((options) => {
|
|
gameType.value = options.gameType;
|
|
teamSize.value = options.teamSize;
|
|
});
|
|
async function startMatch() {
|
|
if (gameType.value && teamSize.value) {
|
|
await matchGameAPI(true, gameType.value, teamSize.value);
|
|
startMatch.value = true;
|
|
}
|
|
}
|
|
async function stopMatch() {
|
|
if (gameType.value && teamSize.value) {
|
|
await matchGameAPI(false, gameType.value, teamSize.value);
|
|
startMatch.value = false;
|
|
}
|
|
}
|
|
async function readyToGo() {
|
|
if (battleId.value) {
|
|
await readyGameAPI(battleId.value);
|
|
start.value = true;
|
|
timerSeq.value = 0;
|
|
}
|
|
}
|
|
|
|
async function onReceiveMessage(content) {
|
|
const messages = JSON.parse(content).data.updates || [];
|
|
messages.forEach((msg) => {
|
|
if (
|
|
!msg.id ||
|
|
(battleId.value && msg.id === battleId.value) ||
|
|
msg.constructor === MESSAGETYPES.WaitForAllReady
|
|
) {
|
|
console.log("收到消息:", msg);
|
|
}
|
|
if (msg.constructor === MESSAGETYPES.WaitForAllReady) {
|
|
// 这里会掉多次;
|
|
timerSeq.value += 1;
|
|
battleId.value = msg.id;
|
|
players.value = [
|
|
...msg.groupUserStatus.redTeam,
|
|
...msg.groupUserStatus.blueTeam,
|
|
];
|
|
players.value.forEach((p) => {
|
|
playersScores.value[p.id] = [];
|
|
});
|
|
}
|
|
if (!start.value && msg.constructor === MESSAGETYPES.ShootSyncMeArrowID) {
|
|
scores.value.push(msg.target);
|
|
power.value = msg.target.battery;
|
|
}
|
|
if (msg.id !== battleId.value) return;
|
|
if (msg.constructor === MESSAGETYPES.MeleeAllReady) {
|
|
totalRounds.value = msg.groupUserStatus.config.maxRounds;
|
|
start.value = true;
|
|
timerSeq.value = 0;
|
|
tips.value = "请在90秒内射完12支箭";
|
|
scores.value = [];
|
|
}
|
|
if (msg.constructor === MESSAGETYPES.ShootResult) {
|
|
if (msg.userId === user.value.id) {
|
|
scores.value = [msg.target];
|
|
power.value = msg.target.battery;
|
|
}
|
|
playersScores.value[msg.userId].push(msg.target);
|
|
}
|
|
if (msg.constructor === MESSAGETYPES.MatchOver) {
|
|
uni.redirectTo({
|
|
url: `/pages/battle-result?battleId=${msg.id}&winner=${msg.endStatus.winner}&gameType=${gameType.value}`,
|
|
});
|
|
}
|
|
});
|
|
}
|
|
onMounted(() => {
|
|
uni.$on("socket-inbox", onReceiveMessage);
|
|
});
|
|
onUnmounted(() => {
|
|
uni.$off("socket-inbox", onReceiveMessage);
|
|
if (startMatch.value) {
|
|
matchGameAPI(false, gameType.value, teamSize.value);
|
|
}
|
|
});
|
|
</script>
|
|
|
|
<template>
|
|
<Container title="大乱斗排位赛" :bgType="1">
|
|
<view class="container">
|
|
<BattleHeader v-if="!start" :players="players" />
|
|
<Guide noBg v-if="!start">
|
|
<view :style="{ display: 'flex', justifyContent: 'space-between' }">
|
|
<view :style="{ display: 'flex', flexDirection: 'column' }">
|
|
<text :style="{ color: '#fed847' }">请预先射几箭测试</text>
|
|
<text>请确保射击距离只有5米</text>
|
|
</view>
|
|
<BowPower :power="45" />
|
|
</view>
|
|
</Guide>
|
|
<ShootProgress v-if="start" :start="start" :tips="tips" />
|
|
<BowTarget
|
|
:avatar="user.avatarUrl"
|
|
:power="power"
|
|
:currentRound="currentRound"
|
|
:totalRound="totalRounds"
|
|
:scores="scores"
|
|
/>
|
|
<PlayerScore
|
|
v-if="start"
|
|
v-for="(player, index) in players"
|
|
:key="index"
|
|
:name="player.name"
|
|
:avatar="player.avatar"
|
|
:scores="playersScores[player.id]"
|
|
/>
|
|
<Timer :seq="timerSeq" :callBack="readyToGo" />
|
|
</view>
|
|
<SButton v-if="!battleId" :onClick="matching ? stopMatch : startMatch">{{
|
|
matching ? "取消匹配" : "开始匹配"
|
|
}}</SButton>
|
|
<SButton v-if="battleId && !start" :onClick="readyToGo">准备完毕</SButton>
|
|
</Container>
|
|
</template>
|
|
|
|
<style scoped>
|
|
.container {
|
|
width: 100%;
|
|
}
|
|
</style>
|