vue3+threejs新手从零开发卡牌游戏(二十三):优化己方游戏流程代码逻辑

时间:2024-03-30 19:43:15

这里优化了一些游戏细节和代码逻辑:

1.添加先手第一回合不能攻击的逻辑

2.卡牌添加攻击次数,默认每回合只能攻击1次

3.卡牌添加资源值(Mana),每回合双方玩家最多只能使用6点能量值,用于召唤怪兽上场或使用物品

主要部分代码如下:

game/index.vue:

// 鼠标选中场上卡牌事件
const onSelectSiteCard = () => {
  if (commonStore.$state.flowIndex !== 2) { // 非战斗阶段不进行该操作
    return
  }
  if (commonStore.$state.round === 1) { // 第一回合不能进行攻击
    return
  }
  let p1Cards = scene.children.filter((v: any) => v.userData?.areaType?.indexOf("己方怪兽区") > -1)
  if (p1Cards.length <= 0) {
    return
  }
  let arr = raycaster.intersectObjects(p1Cards, true)
  if (arr.length > 0) {
    // 找到对应卡牌
    let _selectedCard: any = arr[0].object
    if (_selectedCard.name === "攻击力") {
      _selectedCard = _selectedCard.parent
    }
    if (_selectedCard.userData.AttackFrequency <= 0) { // 如果该卡攻击次数小于等于0,那么跳过
      return
    }
    selectedCard.value = _selectedCard
  }

}
// 获取目标对象
const getTargetMesh = () => {
  let p2Cards = scene.children.filter((v: any) => v.userData?.areaType?.indexOf("对方怪兽区") > -1)
  if (p2Cards.length <= 0) {
    selectedTargetCard.value = null
    return
  }
  let arr = raycaster.intersectObjects(p2Cards, true)
  if (arr.length > 0) {
    let _selectedTargetCard: any = arr[0].object
    if (_selectedTargetCard.name === "攻击力") {
      _selectedTargetCard = _selectedTargetCard.parent
    }
    selectedTargetCard.value = _selectedTargetCard
  } else {
    selectedTargetCard.value = null
  }
}
dragControls.addEventListener( 'dragend', function ( event: any ) {
    if (commonStore.$state.currentPlayer === "p1" && commonStore.$state.flowIndex === 1) {
      dragControls.enabled = true
      event.object.position.y -= 0.04
      // 如果mana不够则不能上场
      if (commonStore.$state.p1Mana < event.object?.userData.Mana) {
        handRef.value.backPosition(event.object)
        return
      }
      let p1SitePlane = scene.getObjectByName("己方战域Plane")
      let point = transPos(pointer.x, pointer.y)
      // 通过摄像机和鼠标位置更新射线
      raycaster.setFromCamera( point, camera );
      const intersects = raycaster.intersectObjects(p1SitePlane.children);
      if (intersects.length > 0) {
        dialogRef.value.init({
          type: "handToSite",
          obj: event.object,
          message: "是否上场该卡牌"
        })
      } else {
        handRef.value.backPosition(event.object)
      }
    } else {
      dragControls.enabled = false
    }
  });
// 绘制场上卡牌
const renderSiteCard = async (handGroup: any, data: any, mesh: any) => {
  let position = new THREE.Vector3(0, 0, 0)
  mesh.getWorldPosition(position)
  mesh.userData.empty = false
  let oldMesh = handGroup.children.find((v: any) => v.name === data.name)
  let newMesh = oldMesh.clone()
  newMesh.userData.areaType = mesh.name // 用来记录卡牌在哪个区域,怪兽区、墓地、手牌、卡组、场地等
  newMesh.scale.set(0.8, 0.8, 0.8)
  if (handGroup.name === "p1_handGroup") {
    // 更新mana
    let mana = JSON.parse(JSON.stringify(commonStore.$state.p1Mana))
    mana -= newMesh.userData.Mana
    commonStore.updateP1Mana(mana)
    // 
    handRef.value.removeP1HandCard(oldMesh)
  } else if (handGroup.name === "p2_handGroup") {
    // 更新mana
    let mana = JSON.parse(JSON.stringify(commonStore.$state.p2Mana))
    mana -= newMesh.userData.Mana
    commonStore.updateP2Mana(mana)
    // 
    handRef.value.removeP2HandCard(oldMesh)
    newMesh.rotateX(180 * (Math.PI / 180)) // 弧度
    newMesh.rotateY(180 * (Math.PI / 180)) // 弧度
  }
  scene.add(newMesh)
  newMesh.position.set(position.x, position.y, position.z)
  await renderSiteCardText(handGroup, newMesh, commonStore.$state._font)

}

game/deck/p1.vue(game/deck/p2.vue同步修改):

const init = () => {
  setDeckPos()
  addDeckWireframe()
  commonStore.$state.p1Deck.forEach((v: any, i: any) => {
    let obj = CARD_DICT.find((b: any) => b.card_id === v.card_id)
    if (obj) {
      let card = new Card(obj)
      let mesh = card.init()
      mesh.position.set(0, 0.005 * i, 0)
      mesh.rotateX(180 * (Math.PI / 180)) // 弧度
      mesh.name = v.name
      mesh.userData._ATK = mesh.userData.ATK // _ATK用于实时计算当前攻击力
      mesh.userData.AttackFrequency = 1 // 攻击次数,初始默认设置为1,即每回合怪兽只能攻击一次
      deckGroup.add( mesh );
    }
  })

  let position = new THREE.Vector3(0, 0.005 * commonStore.$state.p1Deck.length, 0)
  renderDeckText(deckGroup, `${commonStore.$state.p1Deck.length}`, commonStore.$state._font, position)

}

页面效果如下(其中青眼白龙设置为了6能量值,所以此时能量不够无法召唤上场):