首先创建对方场地,game/site/p2.vue和p1.vue代码一样,注意把里面的命名“己方”修改成“对方”,game/site/index.vue代码如下,用rotateZ翻转一下即可得到镜像的对方场地:
// 添加战域plane
const addSitePlane = () => {
return new Promise((resolve, reject) => {
// 设置战域大小和位置
let plane = scene.getObjectByName("地面")
let point = transPos(0, 0) // 战域起始位置的屏幕坐标
//
raycaster.setFromCamera( point, camera );
const intersects = raycaster.intersectObject( plane );
if (intersects.length > 0) {
let point = intersects[0].point
// 进行裁剪
// let x = Math.abs(point.x) * 2 - 2.4
// let y = Math.abs(point.z) * 2 - 4
let x = Math.abs(point.x) * 2
let y = Math.abs(point.z) - 2
// 添加p1战域
const p1SitePlane = new THREE.Group()
p1SitePlane.name = "己方战域Plane"
p1SitePlane.position.set(0, 0, 0.3)
p1SitePlane.rotateX(-90 * (Math.PI / 180)) // 弧度
p1SitePlane.userData["width"] = x
p1SitePlane.userData["height"] = y
scene.add(p1SitePlane)
// 添加p2战域
const p2SitePlane = new THREE.Group()
p2SitePlane.name = "对方战域Plane"
p2SitePlane.position.set(0, 0, -0.3)
p2SitePlane.rotateX(-90 * (Math.PI / 180)) // 弧度
p2SitePlane.rotateZ(-180 * (Math.PI / 180)) // 弧度
p2SitePlane.userData["width"] = x
p2SitePlane.userData["height"] = y
scene.add(p2SitePlane)
resolve(true)
}
})
}
页面效果如下:
然后添加对方卡组,game/deck/p2.vue代码和p1.vue代码一样,注意把里面的命名“己方”修改成“对方”,game/deck/p2.vue代码如下:
<template>
<div></div>
</template>
<script setup lang="ts">
import { reactive, ref, onMounted, onBeforeUnmount, watch, defineComponent, getCurrentInstance, nextTick } from 'vue'
import { useCommonStore } from "@/stores/common.ts"
import { TextGeometry } from 'three/addons/geometries/TextGeometry.js';
import { Card } from "@/views/game/Card.ts"
import { CARD_DICT } from "@/utils/dict/card.ts"
import { transPos, renderDeckText } from "@/utils/common.ts"
// 引入threejs变量
const {proxy} = getCurrentInstance()
const THREE = proxy['THREE']
const scene = proxy['scene']
const camera = proxy['camera']
const renderer = proxy['renderer']
const TWEEN = proxy['TWEEN']
const raycaster = new THREE.Raycaster();
const pointer = new THREE.Vector2();
const commonStore = useCommonStore()
// 卡组group
const deckGroup = new THREE.Group()
deckGroup.name = "p2_deckGroup"
scene.add(deckGroup)
const init = () => {
setDeckPos()
addDeckWireframe()
commonStore.$state.p2Deck.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用于实时计算当前攻击力
deckGroup.add( mesh );
}
})
let position = new THREE.Vector3(0, 0.005 * commonStore.$state.p2Deck.length, 0)
renderDeckText(deckGroup, `${commonStore.$state.p2Deck.length}`, commonStore.$state._font, position)
}
// 设置卡组位置
const setDeckPos = () => {
nextTick(() => {
let sitePlane = scene.getObjectByName("对方战域Plane")
let siteDeckMesh = sitePlane.getObjectByName("对方卡组")
let pos = new THREE.Vector3(0, 0, 0)
siteDeckMesh.getWorldPosition(pos)
deckGroup.position.set(pos.x, pos.y, pos.z)
deckGroup.userData["position"] = pos
deckGroup.scale.set(0.8, 0.8, 0.8) // 缩放
// let plane = scene.getObjectByName("地面")
// let point = transPos(window.innerWidth - 15, window.innerHeight - 15) // 卡组起始位置的屏幕坐标
// //
// raycaster.setFromCamera( point, camera );
// const intersects1 = raycaster.intersectObject( plane );
// if (intersects1.length > 0) {
// let point = intersects1[0].point
// // deckGroup.position.set(point.x, point.y, point.z)
// deckGroup.position.set(point.x - 0.5, point.y, point.z - 0.7)
// // 记录卡组位置
// let position = new THREE.Vector3(point.x - 0.5, point.y, point.z - 0.7)
// deckGroup.userData["position"] = position
// }
})
}
// 绘制卡组区域线框
const addDeckWireframe = () => {
nextTick(() => {
const edges = new THREE.EdgesGeometry( deckGroup.children[0].geometry );
const line = new THREE.LineSegments( edges, new THREE.LineBasicMaterial( { color: 0xffffff } ) );
deckGroup.add(line);
})
}
defineExpose({
init,
})
</script>
<style lang="scss" scoped>
</style>
这里封装下测试卡组,分成p1和p2两个测试卡组:
// p1测试卡组
const p1TestDeck = [
"YZ-01",
"YZ-02",
"YZ-03",
"YZ-04",
"YZ-01",
"YZ-02",
// "YZ-03",
// "YZ-04",
// "YZ-01",
// "YZ-02",
// "YZ-03",
// "YZ-04",
]
export { p1TestDeck }
// p2测试卡组
const p2TestDeck = [
// "YZ-01",
// "YZ-02",
// "YZ-03",
// "YZ-04",
// "YZ-01",
// "YZ-02",
"YZ-03",
"YZ-04",
"YZ-01",
"YZ-02",
"YZ-03",
"YZ-04",
]
export { p2TestDeck }
然后在game/index.vue代码调用,修改初始化卡组方法:
// 初始化卡组
const initDeck = () => {
return new Promise((resolve, reject) => {
let p1Deck: any = []
let p2Deck: any = []
// 洗牌
p1TestDeck.sort(() => {
return Math.random() - 0.5
})
p2TestDeck.sort(() => {
return Math.random() - 0.5
})
p1TestDeck.forEach((v: any, i: any) => {
let obj = CARD_DICT.find((b: any) => b.card_id === v)
if (obj) {
p1Deck.push({
card_id: v,
name: `${obj.name}_${i}`
})
}
})
p2TestDeck.forEach((v: any, i: any) => {
let obj = CARD_DICT.find((b: any) => b.card_id === v)
if (obj) {
p2Deck.push({
card_id: v,
name: `${obj.name}_${i}`
})
}
})
// console.log("p1Deck", newDeck)
commonStore.updateP1Deck(p1Deck)
commonStore.updateP2Deck(p2Deck)
nextTick(() => {
handRef.value.init()
deckRef.value.init()
resolve(true)
})
})
}
页面效果如下: