291 lines
7.7 KiB
Vue
291 lines
7.7 KiB
Vue
<script setup>
|
|
import { ref, watch, onMounted, onBeforeUnmount, computed } from "vue";
|
|
import audioManager from "@/audioManager";
|
|
import { MESSAGETYPESV2 } from "@/constants";
|
|
import { getDirectionText } from "@/util";
|
|
|
|
import useStore from "@/store";
|
|
import { storeToRefs } from "pinia";
|
|
const store = useStore();
|
|
const { user } = storeToRefs(store);
|
|
|
|
const props = defineProps({
|
|
show: {
|
|
type: Boolean,
|
|
default: true,
|
|
},
|
|
start: {
|
|
type: Boolean,
|
|
default: false,
|
|
},
|
|
tips: {
|
|
type: String,
|
|
default: "",
|
|
},
|
|
total: {
|
|
type: Number,
|
|
default: 120,
|
|
},
|
|
currentRound: {
|
|
type: Number,
|
|
default: 0,
|
|
},
|
|
battleId: {
|
|
type: String,
|
|
default: "",
|
|
},
|
|
melee: {
|
|
type: Boolean,
|
|
default: false,
|
|
},
|
|
onStop: {
|
|
type: Function,
|
|
default: () => {},
|
|
},
|
|
});
|
|
|
|
const barColor = ref("#fed847");
|
|
const remain = ref(props.total);
|
|
const timer = ref(null);
|
|
const sound = ref(true);
|
|
const currentRound = ref(props.currentRound);
|
|
const currentRoundEnded = ref(false);
|
|
const ended = ref(false);
|
|
const halfTime = ref(false);
|
|
const wait = ref(0);
|
|
|
|
watch(
|
|
() => props.tips,
|
|
(newVal) => {
|
|
let key = "";
|
|
if (newVal.includes("红队")) key = "请红方射箭";
|
|
if (newVal.includes("蓝队")) key = "请蓝方射箭";
|
|
if (key) {
|
|
if (currentRoundEnded.value) {
|
|
currentRound.value += 1;
|
|
currentRoundEnded.value = false;
|
|
if (currentRound.value === 1) audioManager.play("第一轮");
|
|
if (currentRound.value === 2) audioManager.play("第二轮");
|
|
if (currentRound.value === 3) audioManager.play("第三轮");
|
|
if (currentRound.value === 4) audioManager.play("第四轮");
|
|
if (currentRound.value === 5) audioManager.play("第五轮");
|
|
setTimeout(() => {
|
|
audioManager.play(key);
|
|
}, 1000);
|
|
} else {
|
|
audioManager.play(key);
|
|
}
|
|
}
|
|
}
|
|
);
|
|
|
|
const resetTimer = (count) => {
|
|
if (timer.value) clearInterval(timer.value);
|
|
remain.value = Math.round(count);
|
|
if (remain.value > 0) {
|
|
timer.value = setInterval(() => {
|
|
if (remain.value === 0) {
|
|
clearInterval(timer.value);
|
|
props.onStop();
|
|
}
|
|
if (remain.value > 0) remain.value--;
|
|
}, 1000);
|
|
}
|
|
};
|
|
|
|
watch(
|
|
() => props.start,
|
|
(newVal) => {
|
|
if (newVal) resetTimer(props.total);
|
|
else if (timer.value) clearInterval(timer.value);
|
|
},
|
|
{
|
|
immediate: true,
|
|
}
|
|
);
|
|
|
|
const tipContent = computed(() => {
|
|
if (halfTime.value) {
|
|
return props.battleId ? "中场休息" : `中场休息(${wait.value}秒)`;
|
|
}
|
|
return props.start && remain.value === 0 ? "时间到!" : props.tips;
|
|
});
|
|
|
|
const updateSound = () => {
|
|
sound.value = !sound.value;
|
|
audioManager.setMuted(!sound.value);
|
|
};
|
|
|
|
async function onReceiveMessage(msg) {
|
|
if (Array.isArray(msg)) return;
|
|
if (msg.type === MESSAGETYPESV2.BattleStart) {
|
|
audioManager.play("比赛开始");
|
|
} else if (msg.type === MESSAGETYPESV2.BattleEnd) {
|
|
audioManager.play("比赛结束");
|
|
} else if (msg.type === MESSAGETYPESV2.ShootResult) {
|
|
if (msg.shootData.playerId !== user.value.id) return;
|
|
if (msg.shootData) {
|
|
let key = [];
|
|
key.push(msg.shootData.ring ? `${msg.shootData.ring}环` : "未上靶");
|
|
if (!msg.shootData.ring)
|
|
key.push(`向${getDirectionText(msg.shootData.angle)}调整`);
|
|
audioManager.play(key, false);
|
|
}
|
|
}
|
|
// 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) => {
|
|
audioManager.play(key);
|
|
};
|
|
|
|
onMounted(() => {
|
|
uni.$on("update-remain", resetTimer);
|
|
uni.$on("socket-inbox", onReceiveMessage);
|
|
uni.$on("play-sound", playSound);
|
|
});
|
|
|
|
onBeforeUnmount(() => {
|
|
uni.$off("update-remain", resetTimer);
|
|
uni.$off("socket-inbox", onReceiveMessage);
|
|
uni.$off("play-sound", playSound);
|
|
if (timer.value) clearInterval(timer.value);
|
|
});
|
|
</script>
|
|
|
|
<template>
|
|
<view class="container" :style="{ display: show ? 'block' : 'none' }">
|
|
<view>
|
|
<image src="../static/shooter.png" mode="widthFix" />
|
|
<text>{{ tipContent }}</text>
|
|
<button hover-class="none" @click="updateSound">
|
|
<image
|
|
:src="`../static/sound${sound ? '' : '-off'}-yellow.png`"
|
|
mode="widthFix"
|
|
/>
|
|
</button>
|
|
</view>
|
|
<view>
|
|
<view
|
|
:style="{
|
|
width: `${(remain / total) * 100}%`,
|
|
backgroundColor: barColor,
|
|
right: tips.includes('红队') ? 0 : 'unset',
|
|
}"
|
|
/>
|
|
<text>剩余{{ remain }}秒</text>
|
|
</view>
|
|
</view>
|
|
</template>
|
|
|
|
<style scoped>
|
|
.container {
|
|
width: 100vw;
|
|
}
|
|
.container > view:first-child {
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: space-between;
|
|
padding: 0 15px;
|
|
z-index: 1;
|
|
transform: translateX(-10px);
|
|
}
|
|
.container > view:first-child > image:first-child {
|
|
width: 20vw;
|
|
transform: translateX(10px);
|
|
}
|
|
.container > view:first-child > text {
|
|
color: #fed847;
|
|
font-size: 18px;
|
|
transform: translateY(-10px) translateX(-10px);
|
|
}
|
|
.container > view:first-child > button:last-child {
|
|
overflow: visible;
|
|
}
|
|
.container > view:first-child > button:last-child > image {
|
|
width: 40px;
|
|
transform: translateX(10px) translateY(-10px);
|
|
}
|
|
.container > view:last-child {
|
|
z-index: -1;
|
|
width: calc(100% - 30px);
|
|
margin: 0 15px;
|
|
text-align: center;
|
|
background-color: #ffffff80;
|
|
border-radius: 20px;
|
|
margin-top: -16px;
|
|
font-size: 12px;
|
|
height: 15px;
|
|
line-height: 15px;
|
|
position: relative;
|
|
overflow: hidden;
|
|
}
|
|
.container > view:last-child > view {
|
|
position: absolute;
|
|
height: 15px;
|
|
border-radius: 15px;
|
|
z-index: -1;
|
|
transition: all 1s linear;
|
|
}
|
|
.container > view:last-child > text {
|
|
font-size: 10px;
|
|
line-height: 15px;
|
|
z-index: 1;
|
|
color: #000;
|
|
}
|
|
</style>
|