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

news2025/2/2 15:45:24

首先将双方玩家的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) // 己方HP
  const p2HP = ref(4000) // 对方HP

  const 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
  }

  // 更新己方HP
  function updateP1HP(data: any) {
    p1HP.value = data
  }

  // 更新对方HP
  function 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.value
    let _selectedTargetCard: any = selectedTargetCard.value
    if (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.areaType
      let isP1 = areaType.indexOf("己方") > -1
      let graveyardGroup = null
      let graveyardGroupPos = new THREE.Vector3(0, 0, 0)
      let cards = []
      card.material.forEach((v: any) => {
        v.transparent = false
        v.opacity = 1
        v.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 = null
    selectedTargetCard.value = null
  } else if (selectedCard.value) { // 如果只存在selectedCard
    // 直接攻击
    let _selectedCard: any = selectedCard.value
    console.log(333, _selectedCard)
    if (selectedCard.value.name === "攻击力") {
      _selectedCard = _selectedCard.value.parent
    }
    let areaType = _selectedCard.userData.areaType
    let isP1 = areaType.indexOf("己方") > -1
    let 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.ATK
        if (p2HP < 0) {
          p2HP = 0
        }
        commonStore.updateP2HP(p2HP)
      } else {
        let p1HP = JSON.parse(JSON.stringify(commonStore.$state.p1HP))
        p1HP -= _selectedCard.userData.ATK
        if (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("己方") > -1
  let mesh = null
  if (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 }

页面效果如下:

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1555219.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

常见的Nginx+Redis+MQ+DB架构设计

三高&#xff0c;复杂的架构 SQRS CAP 缓存&#xff0c;限流 【Redis&#xff0c;缓存】 cache-aside 缓存cache&#xff1a;数据源的副本 store 1. Read/Write Through Pattern 读写穿透模式 redis&#xff1a;放当前在线用户&#xff0c;热点数据

iOS UIFont-真香警告之字体管理类

UIFont 系列传送门 第一弹加载本地字体:iOS UIFont-新增第三方字体 第二弹加载线上字体:iOS UIFont-实现三方字体的下载和使用 第三弹搭建字体管理类:iOS UIFont-真香警告之字体管理类 前言 不知道友们是否有过这种经历,项目已经迭代了很多版本,项目中的文件已经上千个了…

ARP协议定义及工作原理

ARP的定义 地址解析协议(Address Resolution Protocol&#xff0c;ARP)&#xff1a;ARP协议可以将IPv4地址(一种逻辑地址)转换为各种网络所需的硬件地址(一种物理地址)。换句话说&#xff0c;所谓的地址解析的目标就是发现逻辑地址与物理地址的映射关系。 ARP仅用于IPv4协议&a…

QT资源添加调用

添加资源文件&#xff0c;新建资源文件夹&#xff0c;命名resource&#xff0c;然后点下一步&#xff0c;点完成 资源&#xff0c;右键add Prefix 添加现有文件 展示的label图片切换 QLabel *led_show; #include "mainwindow.h" #include<QLabel> #include&l…

海豚【货运系统源码】货运小程序【用户端+司机端app】源码物流系统搬家系统源码师傅接单

技术栈&#xff1a;前端uniapp后端vuethinkphp 主要功能&#xff1a; 不通车型配置不通价格参数 多城市定位服务 支持发货地 途径地 目的地智能费用计算 支持日期时间 预约下单 支持添加跟单人数选择 支持下单优惠券抵扣 支持司机收藏订单评价 支持订单状态消息通知 支…

ps 常用命令

ps 常用命令 什么是ps&#xff1f; ps是process status的缩写&#xff0c;用于查看当前系统中运行的进程信息。它提供了关于进程的各种详细信息&#xff0c;如进程 PID、进程状态、CPU 使用情况、内存占用、运行时间等。 常用选项参数 -A &#xff1a;所有的进程均显示出来…

JZ-7-201XMT跳位合位监视专用继电器 220VDC 板后接线,面板安装 JOSEF约瑟

系列型号&#xff1a; JZ-7Y-201XMT跳位合位监视继电器&#xff1b; JZ-7J-201XMT跳位合位监视继电器&#xff1b; JZ-7Y-203XMT跳位合位监视继电器&#xff1b; JZ-7J-203XMT跳位合位监视继电器&#xff1b; JZ-7Y-204XMT跳位合位监视继电器&#xff1b; JZ-7J-204XMT跳…

【御控物联】JavaScript JSON结构转换(11):数组To数组——综合应用

文章目录 一、JSON结构转换是什么&#xff1f;二、术语解释三、案例之《JSON数组 To JSON数组》四、代码实现五、在线转换工具六、技术资料 一、JSON结构转换是什么&#xff1f; JSON结构转换指的是将一个JSON对象或JSON数组按照一定规则进行重组、筛选、映射或转换&#xff0…

Web漏洞-深入WAF注入绕过

目录 简要其他测试绕过 方式一:白名单&#xff08;实战中意义不大&#xff09; 方式二:静态资源 方式三: url白名单 方式四:爬虫白名单 #阿里云盾防SQL注入简要分析 #安全狗云盾SQL注入插件脚本编写 在攻防实战中&#xff0c;往往需要掌握一些特性&#xff0c;比如服务…

基于SSM框架的校园失物招领系统:从设计思路到实现细节

末尾获取源码作者介绍&#xff1a;大家好&#xff0c;我是墨韵&#xff0c;本人4年开发经验&#xff0c;专注定制项目开发 更多项目&#xff1a;CSDN主页YAML墨韵 学如逆水行舟&#xff0c;不进则退。学习如赶路&#xff0c;不能慢一步。 目录 一、项目简介 二、开发技术与环…

在Windows中部署redis

下载redis Windows版redis在GitHub开源&#xff0c;由microsoftarchive维护,项目地址为 https://github.com/microsoftarchive/redis 找到releases&#xff0c;然后在latest中选择msi&#xff0c;或者zip进行下载 安装 msi安装包安装 下载完成后双击运行&#xff0c;同意协…

光伏发电量预测(Python代码,CNN结合LSTM,TensorFlow框架)

1.数据集&#xff08;开始位置&#xff09;&#xff0c;数据集免费下载链接&#xff1a;https://download.csdn.net/download/qq_40840797/89051099 数据集一共8列&#xff0c;第一列是时间&#xff0c;特征列一共有6列&#xff1a;"WindSpeed" - 风速 "Sunshi…

Netty核心原理剖析与RPC实践16-20

Netty核心原理剖析与RPC实践16-20 16 IO 加速&#xff1a;与众不同的 Netty 零拷贝技术 今天的课程我们继续讨论 Netty 实现高性能的另一个高阶特性——零拷贝。零拷贝是一个耳熟能详的词语&#xff0c;在 Linux、Kafka、RocketMQ 等知名的产品中都有使用&#xff0c;通常用于…

最快捷读取xlsx,用python读取excel转换成json

这是中英文json&#xff0c;用在国际化vue上的&#xff0c;业务人员统计的表格&#xff0c;我需要读取进行转换 # -*- coding: utf-8 -*-import pandas as pd import json# 读取Excel文件中的数据 excel_file rD:\解析excel\中英.xlsx df pd.read_excel(excel_file)# 生成中…

阿里云Salesforce CRM功能差异列表 - Winter‘24

阉割版的阿里云Salesforce由于技术和监管等因素与国际版的Salesforce差距很大&#xff01; 一、Winter‘ 24版差异概况&#xff1a; 1.1. 主要版本&#xff1a; 阿里云上的 Salesforce 提供两个版本&#xff0c;用于生产用途的 CN 版本&#xff08;CN Edition&#xff09;和用…

深入MNN:开源深度学习框架的介绍、安装与编译指南

引言 在人工智能的世界里&#xff0c;深度学习框架的选择对于研究和应用的进展至关重要。MNN&#xff0c;作为一个轻量级、高效率的深度学习框架&#xff0c;近年来受到了众多开发者和研究人员的青睐。它由阿里巴巴集团开源&#xff0c;专为移动端设备设计&#xff0c;支持跨平…

基于哈希槽的docker三主三从redis集群配置

目录 一、三主三从redis集群配置 1、关闭防火墙启动docker后台服务 2、新建6个docker容器redis实例 3、进入容器redis-node-1为6台机器构建集群关系 3.1进入容器 3.2构建主从关系 4、查看集群状态 4.1链接进入6381作为切入点 二、主从容错切换迁移按例 1、数据读写存储…

网络安全接入认证-802.1X接入说明

介绍 802.1X是一个网络访问控制协议&#xff0c;它可以通过认证和授权来控制网络访问。它的基本原理是在网络交换机和认证服务器之间建立一个安全的通道&#xff0c;并要求客户端提供身份验证凭据。如果客户端提供的凭据是有效的&#xff0c;交换机将开启端口并允许访问。否则&…

英语广场期刊投稿发表论文

《英语广场》是由国家新闻出版总署批准的正规期刊&#xff0c;杂志本着“轻松读原作&#xff0c;快乐学英语”的宗旨&#xff0c;倡导“寓学于乐”的学习理念&#xff0c;其活泼的办刊风格和优秀的文章选材受到读者特别是广大中学生的广泛欢迎&#xff0c;取得了良好的社会效益…

Window11系统下,VMware安装Ubuntu 18.04虚拟机

本文主要记录Window11系统&#xff0c;VMware安装Ubuntu 18.04虚拟机&#xff0c;主要包括常见的镜像网站下载、硬盘分区、创建虚拟机和Ubuntu系统安装四部分。 &#x1f3a1;导航小助手&#x1f3a1; 1. Ubuntu镜像下载2.磁盘分区3.创建Ubuntu虚拟机4.Ubuntu系统安装 1. Ubun…