Files
shoot-miniprograms/src/pages/first-try.vue
2025-06-28 22:44:30 +08:00

263 lines
7.6 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<script setup>
import { ref, onMounted, onUnmounted } from "vue";
import Guide from "@/components/Guide.vue";
import SButton from "@/components/SButton.vue";
import Swiper from "@/components/Swiper.vue";
import BowTarget from "@/components/BowTarget.vue";
import ShootProgress from "@/components/ShootProgress.vue";
import ScoreResult from "@/components/ScoreResult.vue";
import ScorePanel from "@/components/ScorePanel.vue";
import Container from "@/components/Container.vue";
import Avatar from "@/components/Avatar.vue";
import BowPower from "@/components/BowPower.vue";
import { createPractiseAPI } from "@/apis";
import { generateCanvasImage, checkConnection } from "@/util";
import { MESSAGETYPES } from "@/constants";
import useStore from "@/store";
import { storeToRefs } from "pinia";
const store = useStore();
const { user } = storeToRefs(store);
const { updateUser } = store;
const scores = ref([]);
const step = ref(0);
const total = 12;
const stepButtonTexts = [
"开始",
"进入下一个任务",
"进入下一个任务",
"我准备好了,开始",
"",
"退出新手试炼",
];
const title = ref("新手试炼场");
const start = ref(false);
const practiseResult = ref({});
const power = ref(0);
const btnDisabled = ref(false);
const practiseId = ref("");
const createPractise = async (arrows) => {
const result = await createPractiseAPI(arrows);
if (result) practiseId.value = result.id;
};
async function onReceiveMessage(messages = []) {
messages.forEach((msg) => {
if (msg.constructor === MESSAGETYPES.ShootSyncMeArrowID) {
scores.value.push(msg.target);
power.value = msg.target.battery;
// if (step.value === 2 && msg.target.dst / 100 > 5) {
if (step.value === 2 && msg.target.dst > 5) {
btnDisabled.value = false;
}
}
if (msg.constructor === MESSAGETYPES.ShootSyncMePracticeID) {
if (practiseId.value && practiseId.value === msg.practice.id) {
setTimeout(() => {
start.value = false;
practiseResult.value = {
...msg.practice,
arrows: JSON.parse(msg.practice.arrows),
};
generateCanvasImage(
"shareCanvas",
1,
user.value,
practiseResult.value
);
}, 2000);
}
}
});
}
onMounted(() => {
checkConnection();
uni.$on("socket-inbox", onReceiveMessage);
});
onUnmounted(() => {
uni.$off("socket-inbox", onReceiveMessage);
});
const nextStep = async () => {
if (step.value === 0) {
step.value = 1;
title.value = "凹造型";
} else if (step.value === 1) {
btnDisabled.value = true;
step.value = 2;
title.value = "感知距离";
} else if (step.value === 2) {
step.value = 3;
title.value = "小试牛刀";
} else if (step.value === 3) {
title.value = "新手试炼场";
await createPractise(total);
scores.value = [];
step.value = 4;
start.value = true;
} else if (step.value === 5) {
uni.navigateBack({
delta: 1,
});
}
};
const onClose = () => {
setTimeout(() => {
practiseResult.value = {};
step.value = 5;
}, 500);
};
</script>
<template>
<Container :bgType="1" :title="title">
<view class="container">
<Guide
v-if="step !== 4"
:type="
step === 2
? 2
: step === 5 || (step === 0 && user.nickName.length > 6)
? 1
: 0
"
>
<text v-if="step === 0">
hi<text :style="{ color: '#fed847' }">{{ user.nickName }}</text>
这是新人必刷小任务0基础小白也能快速掌握弓箭技巧和游戏规则哦~
</text>
<text v-if="step === 1"
>这是我们人帅技高的高教练首先请按教练示范尝试自己去做这些动作和手势吧</text
>
<view v-if="step === 2">
<view :style="{ display: 'flex', flexDirection: 'column' }">
<text :style="{ color: '#fed847' }">你知道5米射程有多远吗</text>
<text>
在我们的排位赛中射程小于5米的成绩无效建议平时练习距离至少5米现在来边射箭边调整你的站位点吧
</text>
</view>
</view>
<view v-if="step === 3">
<view :style="{ display: 'flex', flexDirection: 'column' }">
<text :style="{ color: '#fed847' }">一切准备就绪</text>
<text>试着完成一个真正的弓箭手任务吧</text>
</view>
</view>
<view v-if="step === 5">
<view
:style="{ display: 'flex', flexDirection: 'column', marginTop: 20 }"
>
<text :style="{ color: '#fed847' }">新手试炼场通关啦优秀</text>
<text
>反曲弓运动基本知识和射灵世界系统规则你已Get是不是挺容易呀</text
>
<text :style="{ opacity: 0 }">新手试炼场通关啦优秀</text>
</view>
</view>
</Guide>
<image
src="../static/first-try-tip.png"
class="try-tip"
mode="widthFix"
v-if="step === 0"
/>
<image
src="../static/first-try-tip2.png"
class="try-tip"
mode="widthFix"
v-if="step === 3"
/>
<image
src="../static/first-try-tip3.png"
class="try-tip"
mode="widthFix"
v-if="step === 5"
/>
<view style="height: 570px" v-if="step === 1">
<Swiper
:data="[
'../static/first-try-tip.png',
'../static/first-try-tip.png',
'../static/first-try-tip.png',
]"
/>
</view>
<ShootProgress
v-if="step === 4"
tips="请开始连续射箭"
:total="100"
:start="start"
/>
<view
class="infos"
v-if="step === 2 || step === 4"
:style="{ marginBottom: step === 2 ? '40px' : '0' }"
>
<text v-if="step === 2">大人请射箭</text>
<Avatar v-if="step === 4" :src="user.avatar" :size="35" />
<BowPower :power="power" />
</view>
<BowTarget
:start="start"
:avatar="step === 2 ? user.avatar : ''"
:debug="step === 2"
v-if="step === 2 || step === 4"
:currentRound="step === 4 ? scores.length : 0"
:totalRound="step === 4 ? total : 0"
:tips="
step === 2 && scores.length > 0
? `本次射程${scores[scores.length - 1].dst / 100}米,${
scores[scores.length - 1].dst / 100 >= 5 ? '已' : '未'
}达到距离要求`
: ''
"
:scores="scores"
/>
<ScorePanel
v-if="step === 4"
:total="total"
:rowCount="6"
:scores="scores.map((s) => s.ring)"
/>
<ScoreResult
v-if="practiseResult.arrows"
:total="total"
:rowCount="6"
:onClose="onClose"
:result="practiseResult"
tipSrc="../static/first-try-finish-tip.png"
/>
<canvas class="share-canvas" canvas-id="shareCanvas"></canvas>
</view>
<view :style="{ marginBottom: '20px' }">
<SButton v-if="step !== 4" :onClick="nextStep" :disabled="btnDisabled">{{
stepButtonTexts[step]
}}</SButton>
</view>
</Container>
</template>
<style scoped>
.container {
width: 100%;
}
.try-tip {
width: calc(100% - 20px);
margin: 10px 10px;
}
.infos {
display: flex;
align-items: center;
justify-content: space-between;
padding: 0 15px;
padding-top: 20px;
}
.infos > text {
font-size: 20px;
color: #fed847;
}
</style>