225 lines
6.1 KiB
Vue
225 lines
6.1 KiB
Vue
<script setup>
|
||
import { ref, onMounted, onUnmounted } from "vue";
|
||
import { onLoad } from "@dcloudio/uni-app";
|
||
import Container from "@/components/Container.vue";
|
||
import PlayerSeats from "@/components/PlayerSeats.vue";
|
||
import Guide from "@/components/Guide.vue";
|
||
import SButton from "@/components/SButton.vue";
|
||
import BowTarget from "@/components/BowTarget.vue";
|
||
import BattleHeader from "@/components/BattleHeader.vue";
|
||
import BattleFooter from "@/components/BattleFooter.vue";
|
||
import BowPower from "@/components/BowPower.vue";
|
||
import ShootProgress from "@/components/ShootProgress.vue";
|
||
import PlayersRow from "@/components/PlayersRow.vue";
|
||
import { getRoomAPI, destroyRoomAPI, exitRoomAPI, startRoomAPI } from "@/apis";
|
||
import { MESSAGETYPES } from "@/constants";
|
||
import websocket from "@/websocket";
|
||
import useStore from "@/store";
|
||
import { storeToRefs } from "pinia";
|
||
const store = useStore();
|
||
const { user } = storeToRefs(store);
|
||
const step = ref(1);
|
||
const room = ref({});
|
||
const roomNumber = ref("");
|
||
const opponent = ref({});
|
||
const players = new Array(7).fill(1);
|
||
const start = ref(false);
|
||
const teams = [{ name: "选手1", avatar: "../static/avatar.png" }];
|
||
const power = ref(0);
|
||
const scores = ref([]);
|
||
const tips = ref("");
|
||
onLoad(async (options) => {
|
||
if (!options.roomNumber) {
|
||
roomNumber.value = options.roomNumber;
|
||
const result = await getRoomAPI(options.roomNumber || "15655424");
|
||
console.log(11111, result);
|
||
room.value = result;
|
||
}
|
||
});
|
||
const startGame = async () => {
|
||
const result = await startRoomAPI(room.value.number);
|
||
start.value = true;
|
||
console.log(2222, result);
|
||
step.value = 2;
|
||
};
|
||
|
||
async function onReceiveMessage(content) {
|
||
const messages = JSON.parse(content).data.updates || [];
|
||
messages.forEach((msg) => {
|
||
console.log("收到消息:", msg);
|
||
if (msg.constructor === MESSAGETYPES.ShootSyncMeArrowID) {
|
||
scores.value.push(msg.target);
|
||
if (scores.value.length === total) {
|
||
showScore.value = true;
|
||
websocket.closeWebSocket();
|
||
}
|
||
}
|
||
});
|
||
}
|
||
|
||
onMounted(() => {
|
||
uni.$on("socket-inbox", onReceiveMessage);
|
||
});
|
||
|
||
onUnmounted(() => {
|
||
uni.$off("socket-inbox", onReceiveMessage);
|
||
if (user.value.id === room.value.creator) {
|
||
destroyRoomAPI(room.value.id);
|
||
} else {
|
||
exitRoomAPI(room.value.id);
|
||
}
|
||
});
|
||
</script>
|
||
|
||
<template>
|
||
<Container title="对战">
|
||
<view class="standby-phase" v-if="step === 1">
|
||
<Guide>
|
||
<view :style="{ display: 'flex', flexDirection: 'column' }">
|
||
<text :style="{ color: '#fed847' }">人都到齐了吗?</text>
|
||
<text>天赋异禀的弓箭手们,比赛即将开始!</text>
|
||
</view>
|
||
</Guide>
|
||
<view v-if="room.battleType === 1 && room.count === 2" class="team-mode">
|
||
<image src="../static/1v1-bg.png" mode="widthFix" />
|
||
<view>
|
||
<image :src="user.avatarUrl" mode="widthFix" />
|
||
<image src="../static/versus.png" mode="widthFix" />
|
||
<view>
|
||
<image src="../static/question-mark.png" mode="widthFix" />
|
||
</view>
|
||
</view>
|
||
</view>
|
||
<PlayerSeats
|
||
v-if="room.battleType === 2 && room.count === 10"
|
||
:players="players"
|
||
/>
|
||
<view v-if="!start">
|
||
<SButton
|
||
v-if="room.battleType === 1 && room.count === 2"
|
||
:onClick="startGame"
|
||
>进入对战</SButton
|
||
>
|
||
<SButton
|
||
v-if="room.battleType === 2 && room.count === 10"
|
||
:onClick="startGame"
|
||
>进入大乱斗</SButton
|
||
>
|
||
<text class="tips">创建者点击下一步,所有人即可进入游戏。</text>
|
||
</view>
|
||
</view>
|
||
<view v-if="step === 2">
|
||
<BattleHeader />
|
||
<Guide noBg>
|
||
<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>
|
||
<BowTarget
|
||
:tips="
|
||
!start && scores.length > 0
|
||
? `本次射程${scores[scores.length - 1].dst / 100}米,${
|
||
scores[scores.length - 1].dst / 100 >= 5 ? '已' : '未'
|
||
}达到距离要求`
|
||
: ''
|
||
"
|
||
/>
|
||
<SButton :onClick="() => (step = 3)">开始</SButton>
|
||
</view>
|
||
<view v-if="step === 3">
|
||
<ShootProgress tips="请红队射箭-第一轮" />
|
||
<PlayersRow :blueTeam="teams" :redTeam="teams" />
|
||
<BowTarget :power="45" :currentRound="1" :totalRound="3" />
|
||
<BattleFooter :blueTeam="[6, 2, 3]" :redTeam="[4, 5, 2]" />
|
||
</view>
|
||
</Container>
|
||
</template>
|
||
|
||
<style scoped>
|
||
.standby-phase {
|
||
width: 100%;
|
||
height: calc(100% - 40px);
|
||
overflow-x: hidden;
|
||
}
|
||
.founder {
|
||
position: absolute;
|
||
background-color: #fed847;
|
||
top: 0;
|
||
color: #000;
|
||
font-size: 12px;
|
||
padding: 2px 5px;
|
||
border-top-left-radius: 10px;
|
||
border-bottom-right-radius: 10px;
|
||
}
|
||
.player-bg {
|
||
position: absolute;
|
||
width: 52px;
|
||
right: 0;
|
||
}
|
||
.tips {
|
||
color: #fff9;
|
||
width: 100%;
|
||
text-align: center;
|
||
display: block;
|
||
margin-top: 10px;
|
||
font-size: 14px;
|
||
}
|
||
.player-unknow {
|
||
width: 40px;
|
||
height: 40px;
|
||
margin: 0 10px;
|
||
border: 1px solid #fff3;
|
||
border-radius: 50%;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
background-color: #69686866;
|
||
}
|
||
.player-unknow > image {
|
||
width: 40%;
|
||
}
|
||
.team-mode {
|
||
width: calc(100vw - 30px);
|
||
height: 120vw;
|
||
margin: 15px;
|
||
}
|
||
.team-mode > image:first-child {
|
||
position: absolute;
|
||
width: calc(100vw - 30px);
|
||
z-index: -1;
|
||
}
|
||
.team-mode > view {
|
||
display: flex;
|
||
justify-content: center;
|
||
align-items: center;
|
||
height: 95%;
|
||
}
|
||
.team-mode > view > image:first-child {
|
||
width: 70px;
|
||
transform: translateY(-45px);
|
||
border-radius: 50%;
|
||
}
|
||
.team-mode > view > image:nth-child(2) {
|
||
width: 120px;
|
||
}
|
||
.team-mode > view > view:nth-child(3) {
|
||
width: 70px;
|
||
height: 70px;
|
||
border-radius: 50%;
|
||
background-color: #ccc;
|
||
display: flex;
|
||
justify-content: center;
|
||
align-items: center;
|
||
transform: translateY(45px);
|
||
}
|
||
.team-mode > view > view:nth-child(3) > image {
|
||
width: 25px;
|
||
height: 25px;
|
||
margin-right: 2px;
|
||
}
|
||
</style>
|