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) // 己方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 }

页面效果如下:

  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

清岚_lxn

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值