vue3+threejs新手从零开发卡牌游戏(二十一):添加战斗与生命值关联逻辑

本文主要是介绍vue3+threejs新手从零开发卡牌游戏(二十一):添加战斗与生命值关联逻辑,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

首先将双方玩家的HP存入store中,stores/common.ts代码如下:

import { ref, computed } from 'vue'
import { defineStore } from 'pinia'export const useCommonStore = defineStore('common', () => {const _font = ref() // 字体const p1HP = ref(4000) // 己方HPconst p2HP = ref(4000) // 对方HPconst p1Deck = ref([] as any) // 己方卡组const p2Deck = ref([] as any) // 对方卡组const p1Hand = ref([] as any) // 己方手牌const p2Hand = ref([] as any) // 对方手牌const p1SiteCards = ref([] as any) // 己方场上卡牌const p2SiteCards = ref([] as any) // 对方场上卡牌// 加载字体function loadFont(data: any) {_font.value = data}// 更新己方HPfunction updateP1HP(data: any) {p1HP.value = data}// 更新对方HPfunction updateP2HP(data: any) {p2HP.value = data}// 更新己方卡组function updateP1Deck(data: any) {p1Deck.value = data}// 更新对方卡组function updateP2Deck(data: any) {p2Deck.value = data}// 更新己方手牌function updateP1Hand(data: any) {p1Hand.value = data}// 更新己方手牌function updateP2Hand(data: any) {p2Hand.value = data}// 更新己方场上卡牌function updateP1SiteCards(data: any) {p1SiteCards.value = data}// 更新对方场上卡牌function updateP2SiteCards(data: any) {p2SiteCards.value = data}return {_font,p1HP,p2HP,p1Deck,p2Deck,p1Hand,p2Hand,p1SiteCards,p2SiteCards,loadFont,updateP1HP,updateP2HP,updateP1Deck,updateP2Deck,updateP1Hand,updateP2Hand,updateP1SiteCards,updateP2SiteCards,}
}, {persist: true
})

然后思考下血量相关逻辑,这里只做两个简单的处理:
1.卡牌战斗后的攻击力差值导致的血量削减

2.卡牌直接攻击玩家导致的血量削减

所以我们修改game/index.vue中的fight方法,补充了直接攻击和卡牌战斗后差值导致的血量变化逻辑:


// 战斗
const fight = () => {if (selectedCard.value && selectedTargetCard.value) { // 如果selectedCard和selectedTargetCard都存在let _selectedCard: any = selectedCard.valuelet _selectedTargetCard: any = selectedTargetCard.valueif (selectedCard.value.name === "攻击力") {_selectedCard = _selectedCard.value.parent}if (selectedTargetCard.value.name === "攻击力") {_selectedTargetCard = _selectedTargetCard.value.parent}// 移除卡牌const removeCard = async (card: any) => {if (card.children && card.children.length > 0) {card.children.forEach((v: any) => {card.remove(v)})}let areaType = card.userData.areaTypelet isP1 = areaType.indexOf("己方") > -1let graveyardGroup = nulllet graveyardGroupPos = new THREE.Vector3(0, 0, 0)let cards = []card.material.forEach((v: any) => {v.transparent = falsev.opacity = 1v.alphaTest = 0.1;})card.rotateX(180 * (Math.PI / 180)) // 弧度if (isP1) {card.userData.areaType = "己方墓地"graveyardGroup = scene.getObjectByName("p1_graveyardGroup")graveyardGroup.getWorldPosition(graveyardGroupPos)card.position.set(graveyardGroupPos.x, graveyardGroupPos.y, graveyardGroupPos.z)cards = scene.children.filter((v: any) => v.userData?.areaType === "己方墓地")} else {card.userData.areaType = "对方墓地"graveyardGroup = scene.getObjectByName("p2_graveyardGroup")graveyardGroup.getWorldPosition(graveyardGroupPos)card.position.set(graveyardGroupPos.x, graveyardGroupPos.y, graveyardGroupPos.z)cards = scene.children.filter((v: any) => v.userData?.areaType === "对方墓地")}// 修改墓地let position = new THREE.Vector3(0, 0.005 * cards.length, 0)await editGraveyardCard(graveyardGroup, card, "remove")await renderGraveyardText(graveyardGroup, `${cards.length}`, commonStore.$state._font, position)if (isP1) {let sitePlane = scene.getObjectByName("己方战域Plane")let mesh = sitePlane.children.find((v: any) => v.name === areaType)if (mesh) {mesh.userData.empty = true}} else {let sitePlane = scene.getObjectByName("对方战域Plane")let mesh = sitePlane.children.find((v: any) => v.name === areaType)if (mesh) {mesh.userData.empty = true}}}cardAttack(_selectedCard, _selectedTargetCard, () => {console.log(888, Number(_selectedCard.userData.ATK), Number(_selectedTargetCard.userData.ATK))if (Number(_selectedCard.userData.ATK) > Number(_selectedTargetCard.userData.ATK)) {cardDestroy(_selectedTargetCard, () => {removeCard(_selectedTargetCard)let p2HP = JSON.parse(JSON.stringify(commonStore.$state.p2HP))p2HP -= (Number(_selectedCard.userData.ATK) - Number(_selectedTargetCard.userData.ATK))if (p2HP < 0) {p2HP = 0}commonStore.updateP2HP(p2HP)})} else if (Number(_selectedCard.userData.ATK) === Number(_selectedTargetCard.userData.ATK)) {cardDestroy(_selectedCard, () => {removeCard(_selectedCard)})cardDestroy(_selectedTargetCard, () => {removeCard(_selectedTargetCard)})} else {cardDestroy(_selectedCard, () => {removeCard(_selectedCard)let p1HP = JSON.parse(JSON.stringify(commonStore.$state.p1HP))p1HP -= (Number(_selectedTargetCard.userData.ATK) - Number(_selectedCard.userData.ATK))if (p1HP < 0) {p1HP = 0}commonStore.updateP1HP(p1HP)})}})selectedCard.value = nullselectedTargetCard.value = null} else if (selectedCard.value) { // 如果只存在selectedCard// 直接攻击let _selectedCard: any = selectedCard.valueconsole.log(333, _selectedCard)if (selectedCard.value.name === "攻击力") {_selectedCard = _selectedCard.value.parent}let areaType = _selectedCard.userData.areaTypelet isP1 = areaType.indexOf("己方") > -1let cards = []if (isP1) {cards = scene.children.filter((v: any) => v.userData?.areaType?.indexOf("对方怪兽区") > -1)} else {cards = scene.children.filter((v: any) => v.userData?.areaType?.indexOf("己方方怪兽区") > -1)}if (cards.length > 0) {return}cardDirectAttack(scene, _selectedCard, () => {if (isP1) {let p2HP = JSON.parse(JSON.stringify(commonStore.$state.p2HP))p2HP -= _selectedCard.userData.ATKif (p2HP < 0) {p2HP = 0}commonStore.updateP2HP(p2HP)} else {let p1HP = JSON.parse(JSON.stringify(commonStore.$state.p1HP))p1HP -= _selectedCard.userData.ATKif (p1HP < 0) {p1HP = 0}commonStore.updateP1HP(p1HP)}})}
}

然后在utils/common.ts中添加一个卡牌直接攻击特效的方法,和卡牌战斗动效差不多,修改下移动终点的位置即可:


// 卡牌直接攻击特效
const cardDirectAttack = (scene: any, card: any, callback: any) => {// 获取card1世界坐标let pos1 = new THREE.Vector3(0, 0, 0)card.getWorldPosition(pos1)// 获取card2世界坐标let pos2 = new THREE.Vector3(0, 0, 0)let isP1 = card.userData.areaType.indexOf("己方") > -1let mesh = nullif (isP1) {let sitePlane = scene.getObjectByName("对方战域Plane")mesh = sitePlane.children.find((v: any) => v.name === "对方战术2")mesh.getWorldPosition(pos2)} else {let sitePlane = scene.getObjectByName("己方战域Plane")mesh = sitePlane.children.find((v: any) => v.name === "己方战术2")mesh.getWorldPosition(pos2)}// 动画1:移动到对方卡面前const twA = new TWEEN.Tween({x: pos1.x,y: pos1.y,z: pos1.z,card,})twA.to({x: pos2.x,y: pos2.y + 0.1,z: pos2.z,}, 300)twA.easing(TWEEN.Easing.Quadratic.Out)twA.onUpdate((obj: any) => {obj.card.position.set(obj.x, obj.y, obj.z)})twA.onComplete(function() {//动画结束:关闭允许透明,恢复到模型原来状态TWEEN.remove(twA)callback && callback()})// 动画2:退回到原位置const twB = new TWEEN.Tween({x: pos2.x,y: pos2.y + 0.1,z: pos2.z,card,})twB.to({x: pos1.x,y: pos1.y,z: pos1.z,}, 400)twB.easing(TWEEN.Easing.Quadratic.In)twB.onUpdate((obj: any) => {obj.card.position.set(obj.x, obj.y, obj.z)})twB.onComplete(function() {//动画结束:关闭允许透明,恢复到模型原来状态// TWEEN.remove(twA)// callback && callback()})twA.chain(twB)twA.start();
}
export { cardDirectAttack }

页面效果如下:

这篇关于vue3+threejs新手从零开发卡牌游戏(二十一):添加战斗与生命值关联逻辑的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/861001

相关文章

Vue3 的 shallowRef 和 shallowReactive:优化性能

大家对 Vue3 的 ref 和 reactive 都很熟悉,那么对 shallowRef 和 shallowReactive 是否了解呢? 在编程和数据结构中,“shallow”(浅层)通常指对数据结构的最外层进行操作,而不递归地处理其内部或嵌套的数据。这种处理方式关注的是数据结构的第一层属性或元素,而忽略更深层次的嵌套内容。 1. 浅层与深层的对比 1.1 浅层(Shallow) 定义

这15个Vue指令,让你的项目开发爽到爆

1. V-Hotkey 仓库地址: github.com/Dafrok/v-ho… Demo: 戳这里 https://dafrok.github.io/v-hotkey 安装: npm install --save v-hotkey 这个指令可以给组件绑定一个或多个快捷键。你想要通过按下 Escape 键后隐藏某个组件,按住 Control 和回车键再显示它吗?小菜一碟: <template

【 html+css 绚丽Loading 】000046 三才归元阵

前言:哈喽,大家好,今天给大家分享html+css 绚丽Loading!并提供具体代码帮助大家深入理解,彻底掌握!创作不易,如果能帮助到大家或者给大家一些灵感和启发,欢迎收藏+关注哦 💕 目录 📚一、效果📚二、信息💡1.简介:💡2.外观描述:💡3.使用方式:💡4.战斗方式:💡5.提升:💡6.传说: 📚三、源代码,上代码,可以直接复制使用🎥效果🗂️目录✍️

Hadoop企业开发案例调优场景

需求 (1)需求:从1G数据中,统计每个单词出现次数。服务器3台,每台配置4G内存,4核CPU,4线程。 (2)需求分析: 1G / 128m = 8个MapTask;1个ReduceTask;1个mrAppMaster 平均每个节点运行10个 / 3台 ≈ 3个任务(4    3    3) HDFS参数调优 (1)修改:hadoop-env.sh export HDFS_NAMENOD

【前端学习】AntV G6-08 深入图形与图形分组、自定义节点、节点动画(下)

【课程链接】 AntV G6:深入图形与图形分组、自定义节点、节点动画(下)_哔哩哔哩_bilibili 本章十吾老师讲解了一个复杂的自定义节点中,应该怎样去计算和绘制图形,如何给一个图形制作不间断的动画,以及在鼠标事件之后产生动画。(有点难,需要好好理解) <!DOCTYPE html><html><head><meta charset="UTF-8"><title>06

嵌入式QT开发:构建高效智能的嵌入式系统

摘要: 本文深入探讨了嵌入式 QT 相关的各个方面。从 QT 框架的基础架构和核心概念出发,详细阐述了其在嵌入式环境中的优势与特点。文中分析了嵌入式 QT 的开发环境搭建过程,包括交叉编译工具链的配置等关键步骤。进一步探讨了嵌入式 QT 的界面设计与开发,涵盖了从基本控件的使用到复杂界面布局的构建。同时也深入研究了信号与槽机制在嵌入式系统中的应用,以及嵌入式 QT 与硬件设备的交互,包括输入输出设

OpenHarmony鸿蒙开发( Beta5.0)无感配网详解

1、简介 无感配网是指在设备联网过程中无需输入热点相关账号信息,即可快速实现设备配网,是一种兼顾高效性、可靠性和安全性的配网方式。 2、配网原理 2.1 通信原理 手机和智能设备之间的信息传递,利用特有的NAN协议实现。利用手机和智能设备之间的WiFi 感知订阅、发布能力,实现了数字管家应用和设备之间的发现。在完成设备间的认证和响应后,即可发送相关配网数据。同时还支持与常规Sof

活用c4d官方开发文档查询代码

当你问AI助手比如豆包,如何用python禁止掉xpresso标签时候,它会提示到 这时候要用到两个东西。https://developers.maxon.net/论坛搜索和开发文档 比如这里我就在官方找到正确的id描述 然后我就把参数标签换过来

Linux_kernel驱动开发11

一、改回nfs方式挂载根文件系统         在产品将要上线之前,需要制作不同类型格式的根文件系统         在产品研发阶段,我们还是需要使用nfs的方式挂载根文件系统         优点:可以直接在上位机中修改文件系统内容,延长EMMC的寿命         【1】重启上位机nfs服务         sudo service nfs-kernel-server resta

计算机毕业设计 大学志愿填报系统 Java+SpringBoot+Vue 前后端分离 文档报告 代码讲解 安装调试

🍊作者:计算机编程-吉哥 🍊简介:专业从事JavaWeb程序开发,微信小程序开发,定制化项目、 源码、代码讲解、文档撰写、ppt制作。做自己喜欢的事,生活就是快乐的。 🍊心愿:点赞 👍 收藏 ⭐评论 📝 🍅 文末获取源码联系 👇🏻 精彩专栏推荐订阅 👇🏻 不然下次找不到哟~Java毕业设计项目~热门选题推荐《1000套》 目录 1.技术选型 2.开发工具 3.功能