You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
174 lines
5.4 KiB
174 lines
5.4 KiB
<template> |
|
<div v-if="dungeon" class="battle"> |
|
<div class="player"> |
|
<img class="player-icon" :src="dungeon_icon.player"> |
|
</div> |
|
<div class="monster" v-for="(v, k) in dungeon.monsters" :key="k" |
|
:style="{ left: (95 / dungeon.monsters.length) * (k + 1) + '%' }"> |
|
<img :src="dungeon_icon[v.type]"> |
|
</div> |
|
<div class="progress-bar"></div> |
|
<button @click="stopDungeon" class="button">{{ t('stopDungeon.0') }}</button> |
|
</div> |
|
</template> |
|
|
|
<script lang="ts" setup> |
|
import { useStore } from "vuex"; |
|
import { computed, nextTick, onMounted, ref } from "vue"; |
|
import { useI18n } from "vue3-i18n"; |
|
import { dungeon_icon, player_move_time, player_battle_time } from "@/config"; |
|
import { randonBootyEquip, callBattleResult } from "@/tool"; |
|
|
|
const { t } = useI18n(); |
|
const { state, commit, dispatch } = useStore(); |
|
const battle = computed(() => { |
|
return state.battle; |
|
}) |
|
|
|
const props = defineProps({ |
|
dungeon: { |
|
type: Object, |
|
} |
|
}) |
|
|
|
const startDungeon = () => { |
|
const dungeon = props.dungeon; |
|
if (!dungeon) { |
|
return; |
|
} |
|
dispatch('play_music', 'battle'); |
|
playerMove(0, 0); |
|
const msg = t('startDungeon') + 'lv' + dungeon.lv + '_' + t('difficulty.' + dungeon.difficulty); |
|
commit("set_sys_info", { msg: msg, type: 'warning' }); |
|
} |
|
|
|
defineExpose({ startDungeon }) |
|
|
|
const stopDungeon = () => { |
|
for (let i = 0; i < 5; i++) { |
|
clearTimeout(battle.value.timeOut); |
|
} |
|
battle.value.battleShow = false; |
|
dispatch('play_music', 'backgound'); |
|
commit("set_sys_info", { msg: t('stopDungeon.1'), type: 'warning' }); |
|
} |
|
|
|
const exploreDungeon = (monsterIdx) => { |
|
let idx2 = monsterIdx || 0; |
|
const dungeon = props.dungeon; |
|
if (!dungeon) { |
|
return; |
|
} |
|
const monster = dungeon.monsters[idx2]; |
|
battleWithMonster(monster).then(rsp => { |
|
idx2++; |
|
if (idx2 < dungeon.monsters.length) { |
|
playerMove(idx2); |
|
} else { |
|
commit("set_sys_info", { msg: t('dungeonSuccess'), type: 'battle' }); |
|
if (dungeon.lv > state.playerAttribute.lv) { |
|
commit('set_player_lv', dungeon.lv) |
|
commit('set_sys_info', { msg: t('upgrade'), type: 'win' }) |
|
} |
|
if (dungeon.difficulty != 1) { |
|
dungeon.setDifficulty(1); |
|
battle.value.battleShow = false; |
|
dispatch('play_music', 'backgound'); |
|
} else { |
|
playerMove(0, 0); |
|
} |
|
} |
|
}) |
|
} |
|
|
|
const playerMove = (monsterIdx?, playerIdx?) => { |
|
let idx2 = playerIdx || 0; |
|
const max = 20; |
|
const lenght = 95 / props.dungeon?.monsters.length; |
|
const left = monsterIdx * lenght + lenght / (max + 1) * idx2; |
|
battle.value.left = + left + '%'; |
|
const position = Math.floor(left % 4) * 32; |
|
battle.value.imgLeft = -1 * position + 'px'; |
|
battle.value.clip = 'rect(96px, ' + (position + 32) + 'px, 144px, ' + position + 'px)' |
|
if (idx2 > max) { |
|
exploreDungeon(monsterIdx); |
|
} else { |
|
idx2++; |
|
const moveTime = Math.round(player_move_time * 100 / (100 + state.rebornAttribute.moveSpeed) / max); |
|
battle.value.timeOut = setTimeout(() => { |
|
playerMove(monsterIdx, idx2); |
|
}, moveTime); |
|
} |
|
} |
|
|
|
const battleWithMonster = (monster) => { |
|
return new Promise((resolve, reject) => { |
|
const player = state.playerAttribute.attribute; |
|
const battleTime = Math.round(player_battle_time * 100 / (100 + state.rebornAttribute.battleSpeed)) |
|
const getMsg = (i18nName, takeDmg) => { |
|
return t(i18nName).replace('${lv}', monster.lv).replace('${name}', t('difficulty.' + props.dungeon?.difficulty) + t(monster.type)).replace('${dmg}', takeDmg + ''); |
|
}; |
|
commit("set_sys_info", { msg: getMsg('battle', 0), type: 'battle' }); |
|
battle.value.timeOut = setTimeout(() => { |
|
const result = callBattleResult(player, monster); |
|
nextTick(() => { |
|
commit('add_player_curhp', -1 * result.takeDmg); |
|
}) |
|
if (result.win) { |
|
commit("set_sys_info", { msg: getMsg('killMonster', result.takeDmg), type: 'battle', bouts: result.bouts }); |
|
//随机获取装备战利品 |
|
const equips = randonBootyEquip(monster); |
|
commit('add_bootys', { equips: equips, coins: monster.coins }); |
|
resolve(true); |
|
} else { |
|
commit("set_sys_info", { msg: getMsg('beKilled', result.takeDmg), type: 'warning', bouts: result.bouts }); |
|
battle.value.battleShow = false; |
|
dispatch('play_music', 'backgound'); |
|
} |
|
}, battleTime); |
|
}); |
|
} |
|
|
|
onMounted(() => { }); |
|
</script> |
|
<style lang="scss" scoped> |
|
.battle { |
|
width: 100%; |
|
|
|
.player { |
|
overflow: hidden; |
|
position: absolute; |
|
z-index: 2; |
|
top: 1.2rem; |
|
height: 48px; |
|
width: 32px; |
|
left: v-bind('state.battle.left'); |
|
|
|
.player-icon { |
|
top: -96px; |
|
left: v-bind('state.battle.imgLeft'); |
|
position: absolute; |
|
clip: v-bind('state.battle.clip'); |
|
} |
|
} |
|
|
|
.monster { |
|
position: absolute; |
|
top: 2rem; |
|
} |
|
|
|
.progress-bar { |
|
position: absolute; |
|
top: 5rem; |
|
left: 0.7rem; |
|
right: 0.7rem; |
|
border: 1px solid #fff; |
|
} |
|
|
|
.button { |
|
position: absolute; |
|
top: 6rem; |
|
right: 1.2rem; |
|
} |
|
} |
|
</style> |