首先在utils/common.ts里定义一些流程相关的变量:
javascript
const flow = ref([ // 游戏流程
{
name: "抽卡阶段"
},
{
name: "主要阶段"
},
{
name: "战斗阶段"
},
{
name: "结束阶段"
}
])
const flowIndex = ref(0) // 当前流程
const currentPlayer = ref("p1") // 当前玩家
const round = ref(1) // 回合数
然后修改game/index.vue代码,主要是将流程、当前玩家的逻辑融入之前的操作逻辑中,根据流程节点进行判断哪些交互可以做,哪些交互不可以做,这里直接贴了game/index.vue的完整代码,代码比较长感兴趣的可以看下:
javascript
<template>
<div ref="sceneRef" class="scene"></div>
<!-- 玩家区 -->
<Player ref="playerRef"/>
<!-- 手牌 -->
<Hand ref="handRef"/>
<!-- 卡组 -->
<Deck ref="deckRef"/>
<!-- 战域 -->
<Site ref="siteRef"/>
<!-- 墓地 -->
<Graveyard ref="graveyardRef"/>
<!-- 抽卡逻辑 -->
<DrawCard ref="drawCardRef" :handRef="handRef"/>
<!-- 对话框 -->
<Dialog ref="dialogRef" @handToSite="handToSite" @onCancel="onCancel"/>
<!-- 阶段操作 -->
<ul class="stage-box">
<li v-if="commonStore.$state.flowIndex==1">
<el-button type="primary" size="small" @click.stop="nextFlow">下一阶段</el-button>
</li>
<li v-if="commonStore.$state.flowIndex===2">
<el-button type="danger" size="small" round @click.stop="nextRound">回合结束</el-button>
</li>
</ul>
</template>
<script setup lang="ts">
import { reactive, ref, onMounted, onBeforeUnmount, watch, defineComponent, getCurrentInstance, nextTick } from 'vue'
import { OrbitControls } from 'three/addons/controls/OrbitControls.js'; // 轨道控制器
import { DragControls } from 'three/addons/controls/DragControls.js';
import { RenderPass } from 'three/addons/postprocessing/RenderPass.js';
import { GlitchPass } from 'three/addons/postprocessing/GlitchPass.js';
import { ShaderPass } from 'three/addons/postprocessing/ShaderPass.js';
import { GammaCorrectionShader } from 'three/examples/jsm/shaders/GammaCorrectionShader.js';
import { OutputPass } from 'three/addons/postprocessing/OutputPass.js';
import { OutlinePass } from 'three/examples/jsm/postprocessing/OutlinePass.js';
import { FontLoader } from 'three/addons/loaders/FontLoader.js';
import { useCommonStore } from "@/stores/common.ts"
import { transPos, editDeckCard, renderDeckText, editGraveyardCard, renderGraveyardText, renderSiteCardText, cardAttack, cardDestroy, cardDirectAttack } from "@/utils/common.ts"
import { Card } from "./Card.ts"
import { CARD_DICT } from "@/utils/dict/card.ts"
import { p1TestDeck, p2TestDeck} from "@/utils/deck/test.ts"
import Hand from "./hand/index.vue"
import Deck from "./deck/index.vue"
import Site from "./site/index.vue"
import Player from "./player/index.vue"
import Graveyard from "./graveyard/index.vue"
import DrawCard from "@/components/DrawCard.vue"
import Dialog from "@/components/Dialog.vue"
import { resolve } from 'dns';
// 引入threejs变量
const {proxy} = getCurrentInstance()
const THREE = proxy['THREE']
const scene = proxy['scene']
const camera = proxy['camera']
const renderer = proxy['renderer']
const composer = proxy['composer']
const TWEEN = proxy['TWEEN']
// 后期处理
const renderPass = new RenderPass( scene, camera );
composer.addPass( renderPass );
//
const raycaster = new THREE.Raycaster();
const pointer = new THREE.Vector2();
const commonStore = useCommonStore()
// 场景ref
const sceneRef = ref()
const playerRef = ref()
const siteRef = ref()
const handRef = ref()
const deckRef = ref()
const graveyardRef = ref()
const drawCardRef = ref()
const dialogRef = ref()
const selectedCard = ref() // 选中的场上card
const selectedTargetCard = ref() // 选中的目标场上card
// 坐标轴辅助
const axesHelper = new THREE.AxesHelper(5);
// 创建轨道控制器
// const orbitControls = new OrbitControls( camera, renderer.domElement );
// 字体加载器
const fontLoader = new FontLoader();
watch(() => commonStore.$state.p1HP, () => {
if (commonStore.$state.p1HP <=0) {
// alert("你输了")
// window.location.reload()
}
})
watch(() => commonStore.$state.p2HP, () => {
if (commonStore.$state.p2HP <=0) {
// alert("你赢了")
// window.location.reload()
}
})
onMounted(async () => {
await initResource()
initScene()
initGame()
// 鼠标按下
window.addEventListener('touchstart', onMousedown)
window.addEventListener('touchmove', onMousemove)
window.addEventListener('touchend', onMouseup)
// window.addEventListener('click', onMousedown)
// 监听浏览器窗口变化进行场景自适应
window.addEventListener('resize', onWindowResize, false);
})
// 资源加载
const initResource = () => {
// 字体加载
return new Promise((resolve, reject) => {
// Microsoft YaHei_Regular
// fonts/helvetiker_regular.typeface.json
fontLoader.load('fonts/helvetiker_bold.typeface.json', (font: any) => {
commonStore.loadFont(font)
resolve(true)
});
})
}
// 初始化场景
const initScene = async () => {
renderer.setSize( window.innerWidth, window.innerHeight );
sceneRef.value.appendChild( renderer.domElement );
scene.add(axesHelper)
// addSceneBg()
// camera.position.set( 5, 5, 5 );
camera.position.set( 0, 6.5, 0 );
camera.lookAt(0, 0, 0)
// const glitchPass = new GlitchPass();
// composer.addPass( glitchPass );
// const outputPass = new OutputPass();
// composer.addPass( outputPass );
addPlane()
animate();
}
// scene添加动态背景
const addSceneBg = () => {
const vertices = [];
for ( let i = 0; i < 5000; i ++ ) {
const x = THREE.MathUtils.randFloatSpread( 1000 );
const y = THREE.MathUtils.randFloatSpread( 1000 );
const z = THREE.MathUtils.randFloatSpread( 1000 );
vertices.push( x, y, z );
}
const particlesGeometry = new THREE.BufferGeometry();
particlesGeometry.setAttribute( 'position', new THREE.Float32BufferAttribute( vertices, 3 ) );
// 设置点材质
const pointsMaterial = new THREE.PointsMaterial();
// pointsMaterial.size = 0.9;
pointsMaterial.color.set(new THREE.Color("#fff"));
// 相机深度而衰减
pointsMaterial.sizeAttenuation = true;
const points = new THREE.Points(particlesGeometry, pointsMaterial);
scene.add(points);
// const texture = new THREE.TextureLoader().load( "textures/bg.jpg" );
// // const geometry = new THREE.SphereGeometry( 1, 32, 16 );
// const geometry = new THREE.CircleGeometry( 6, 32 );
// const material = new THREE.MeshBasicMaterial({
// map: texture
// });
// const sphere = new THREE.Mesh( geometry, material );
// sphere.name = "场景背景"
// sphere.position.set(0, 0, 0)
// sphere.rotateX(-90 * (Math.PI / 180)) // 弧度
// scene.add( sphere );
// texture.wrapS = THREE.RepeatWrapping;
// texture.wrapT = THREE.RepeatWrapping;
// scene.background = texture
}
// scene中添加plane几何体
const addPlane = () => {
const geometry = new THREE.PlaneGeometry( 20, 20);
const material = new THREE.MeshBasicMaterial( {
color: new THREE.Color("gray"),
side: THREE.FrontSide,
alphaHash: true,
// alphaTest: 0,
opacity: 0
} );
const plane = new THREE.Mesh( geometry, material );
plane.rotateX(-90 * (Math.PI / 180)) // 弧度
plane.name = "地面"
scene.add( plane );
}
// 用requestAnimationFrame进行渲染循环
// let bgMesh = scene.getObjectByName("场景背景")
// console.log(123, bgMesh)
// 移动线纹理
let arrowTexture = new THREE.TextureLoader().load('textures/arrow.png');
arrowTexture.wrapT = THREE.RepeatWrapping;
arrowTexture.repeat.set(1, 4);
arrowTexture.center = new THREE.Vector2(0.5, 0.5)
arrowTexture.rotation = (-90 * (Math.PI / 180))
arrowTexture.needsUpdate = true;
const animate = () => {
requestAnimationFrame( animate );
if (arrowTexture) {
arrowTexture.offset.y -= 0.02; //更新箭头纹理偏移量
}
TWEEN.update()
// let bgMesh = scene.getObjectByName("场景背景")
// if (bgMesh) {
// bgMesh.rotation.z += 0.0002
// }
// renderer.render( scene, camera );
composer.render()
}
// 场景跟随浏览器窗口大小自适应
const onWindowResize = () => {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
}
// 初始化游戏
const initGame = async () => {
// 初始化生命值
commonStore.updateP1HP(4000)
commonStore.updateP2HP(4000)
// 初始化游戏流程
commonStore.updateFlowIndex(0)
// 确定先后手
initFirst()
// 初始化玩家
initPlayer()
// 初始化场地
initSite()
// 初始化墓地
initGraveyard()
// 初始化卡组
await initDeck()
// 初始化手牌
await initHand()
// 绑定手牌事件
onHandEvent()
// 执行游戏流
if (commonStore.$state.currentPlayer === "p1") {
// p1Flow()
p1DrawCardEvent()
} else {
}
//
// await p2DrawCardEvent(1)
// let p2_handGroup = scene.getObjectByName("p2_handGroup")
// let cards = p2_handGroup.children.filter((v: any) => v.userData.type === "怪兽")
// p2HandToSite(cards[0])
}
// 确定先后手
const initFirst = () => {
let index = Math.random() * 10
if (index > 0) { // p1先手
commonStore.updateCurrentPlayer("p1")
console.log("p1先手")
} else { // p1后手
commonStore.updateCurrentPlayer("p2")
console.log("p2先手")
}
}
// 初始化玩家
const initPlayer = () => {
playerRef.value.init()
}
// 初始化场地
const initSite = () => {
siteRef.value.init()
}
// 初始化墓地
const initGraveyard = () => {
graveyardRef.value.init()
}
// 初始化卡组
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)
})
})
}
// 初始化手牌
const initHand = () => {
let p1 = new Promise((resolve, reject) => {
let cardNumber = 4
let _number = 0
let p1Deck = JSON.parse(JSON.stringify(commonStore.$state.p1Deck))
let deckGroup = scene.getObjectByName("p1_deckGroup")
let position = new THREE.Vector3(0, 0.005 * p1Deck.length, 0)
let _interval = setInterval(async() => {
// console.log(123, p1Deck)
if (_number < cardNumber) {
let obj = p1Deck[p1Deck.length - 1]
p1Deck.splice(p1Deck.length-1, 1)
commonStore.updateP1Deck(p1Deck)
// 修改卡组
await editDeckCard(deckGroup, obj, "remove")
await renderDeckText(deckGroup, `${commonStore.$state.p1Deck.length}`, commonStore.$state._font, position)
// 手牌区添加手牌
handRef.value.addP1HandCard(obj, deckGroup)
} else {
clearInterval(_interval)
resolve(true)
}
_number++
}, 200)
})
let p2 = new Promise((resolve, reject) => {
let cardNumber = 4
let _number = 0
let p2Deck = JSON.parse(JSON.stringify(commonStore.$state.p2Deck))
let deckGroup = scene.getObjectByName("p2_deckGroup")
let position = new THREE.Vector3(0, 0.005 * p2Deck.length, 0)
let _interval = setInterval(async() => {
// console.log(123, p1Deck)
if (_number < cardNumber) {
let obj = p2Deck[p2Deck.length - 1]
p2Deck.splice(p2Deck.length-1, 1)
commonStore.updateP2Deck(p2Deck)
// 修改卡组
await editDeckCard(deckGroup, obj, "remove")
await renderDeckText(deckGroup, `${commonStore.$state.p2Deck.length}`, commonStore.$state._font, position)
// 手牌区添加手牌
handRef.value.addP2HandCard(obj, deckGroup)
} else {
clearInterval(_interval)
resolve(true)
}
_number++
}, 200)
})
return new Promise((resolve, reject) => {
Promise.all([p1, p2]).then((res: any) => {
resolve(true)
})
})
}
// 玩家1游戏流程
const p1Flow = () => {
// 抽牌
p1DrawCardEvent()
// 主要阶段
// 战斗阶段
// 结束阶段
}
// p1抽牌事件
const p1DrawCardEvent = () => {
setTimeout(() => {
if (commonStore.$state.p1Deck.length <= 0) {
return
}
let p1_deckGroup = scene.getObjectByName("p1_deckGroup")
let pos1 = p1_deckGroup.userData.position
let pos2 = new THREE.Vector3(0, 2, 0)
if (p1_deckGroup.position.x !== pos2.x) {
drawCardRef.value.drawCardAnimate1(p1_deckGroup, pos1, pos2)
}
}, 300)
}
// p2抽牌事件
const p2DrawCardEvent = (cardNumber: any) => {
return new Promise((resolve, reject) => {
let _number = 0
let p2Deck = JSON.parse(JSON.stringify(commonStore.$state.p2Deck))
let deckGroup = scene.getObjectByName("p2_deckGroup")
let position = new THREE.Vector3(0, 0.005 * p2Deck.length, 0)
let _interval = setInterval(async() => {
// console.log(123, p1Deck)
if (_number < cardNumber) {
let obj = p2Deck[p2Deck.length - 1]
p2Deck.splice(p2Deck.length-1, 1)
commonStore.updateP2Deck(p2Deck)
// 修改卡组
await editDeckCard(deckGroup, obj, "remove")
await renderDeckText(deckGroup, `${commonStore.$state.p2Deck.length}`, commonStore.$state._font, position)
// 手牌区添加手牌
handRef.value.addP2HandCard(obj, deckGroup)
} else {
clearInterval(_interval)
resolve(true)
}
_number++
}, 200)
})
}
// p2卡牌上场事件
const p2HandToSite = (card: any) => {
let sitePlane = scene.getObjectByName("对方战域Plane")
let userData = card.userData
if (userData.type === "怪兽") {
let meshes = sitePlane.children.filter((v: any) => v.name.indexOf("对方怪兽区") > -1 && v.userData.empty === true)
if (meshes.length > 0) {
let _mesh = null
let m1 = meshes.find((v: any) => v.name.indexOf(1) > -1)
let m2 = meshes.find((v: any) => v.name.indexOf(2) > -1)
let m3 = meshes.find((v: any) => v.name.indexOf(3) > -1)
if (m2) {
_mesh = m2
} else if (m1) {
_mesh = m1
} else if (m3) {
_mesh = m3
}
let p2_handGroup = scene.getObjectByName("p2_handGroup")
// card.rotateX(180 * (Math.PI / 180)) // 弧度
renderSiteCard(p2_handGroup, card, _mesh)
}
}
}
// 鼠标按下事件
const onMousedown = (ev: any) => {
// console.log(222, ev.target)
// 判断是否点击到canvas上
if(!(ev.target instanceof HTMLCanvasElement)){
return;
}
// 将鼠标位置归一化为设备坐标。x 和 y 方向的取值范围是 (-1 to +1)
let clientX = ev.clientX || ev.changedTouches[0].pageX
let clientY = ev.clientY || ev.changedTouches[0].pageY
let point = transPos(clientX, clientY)
// 通过摄像机和鼠标位置更新射线
raycaster.setFromCamera( point, camera );
// 点击卡组事件
// onP1DeckEvent()
// 鼠标选中场上卡牌事件
onSelectSiteCard()
}
// 鼠标移动事件
const onMousemove = (ev: any) => {
// 将鼠标位置归一化为设备坐标。x 和 y 方向的取值范围是 (-1 to +1)
pointer.x = ev.clientX || ev.changedTouches[0].pageX
pointer.y = ev.clientY || ev.changedTouches[0].pageY
// 画线
if (selectedCard.value && (commonStore.$state.flowIndex === 2)) {
drawLine()
}
}
// 鼠标抬起事件
const onMouseup = (ev: any) => {
let lineMesh = scene.getObjectByName("移动线")
if (lineMesh) {
scene.remove(lineMesh)
}
fight()
}
// 鼠标选中场上卡牌事件
const onSelectSiteCard = () => {
if (commonStore.$state.flowIndex !== 2) {
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) {
selectedCard.value = arr[0].object
// drawLine()
}
}
// 画线
const drawLine = () => {
let mesh = scene.getObjectByName("移动线")
if (mesh) {
scene.remove(mesh)
}
let startPos = new THREE.Vector3(0, 0, 0)
selectedCard.value.getWorldPosition(startPos)
let point = transPos(pointer.x, pointer.y)
// 通过摄像机和鼠标位置更新射线
raycaster.setFromCamera( point, camera );
let plane = scene.getObjectByName("地面")
let arr = raycaster.intersectObject(plane)
if (arr.length > 0) {
// let pos = new THREE.Vector3(0, 0, 0)
// arr[0].object.getWorldPosition(pos)
let point = arr[0].point
let curve = new THREE.CatmullRomCurve3([
new THREE.Vector3(startPos.x, startPos.y + 0.2, startPos.z),
new THREE.Vector3(point.x, point.y + 0.2, point.z)
]);
let tubeGeometry = new THREE.TubeGeometry(curve, 80, 0.08);
const material = new THREE.MeshBasicMaterial({
map: arrowTexture,
side: THREE.BackSide, //显示背面
transparent: true,
// color: new THREE.Color("#ff6347")
});
const _mesh = new THREE.Mesh( tubeGeometry, material );
_mesh.name = "移动线"
scene.add(_mesh);
}
// 获取目标对象
getTargetMesh()
}
// 获取目标对象
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) {
selectedTargetCard.value = arr[0].object
} else {
selectedTargetCard.value = null
}
}
// 战斗
const fight = () => {
if (commonStore.$state.flowIndex !== 2) {
return
}
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 plane = scene.getObjectByName("对方战域Plane")
let arr = raycaster.intersectObjects(plane.children)
if (arr.length <= 0) {
return
}
let _selectedCard: any = selectedCard.value
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)
}
})
}
selectedCard.value = null
}
// 手牌事件
const onHandEvent = () => {
let handGroup = scene.getObjectByName("p1_handGroup")
const dragControls = new DragControls( handGroup.children, camera, renderer.domElement );
dragControls.addEventListener( 'dragstart', function ( event: any ) {
if (commonStore.$state.currentPlayer === "p1" && commonStore.$state.flowIndex === 1) {
dragControls.enabled = true
event.object.position.y += 0.04
} else {
dragControls.enabled = false
}
});
dragControls.addEventListener( 'drag', function ( event: any ) {
if (commonStore.$state.currentPlayer === "p1" && commonStore.$state.flowIndex === 1) {
dragControls.enabled = true
event.object.position.y += 0.04
} else {
dragControls.enabled = false
}
});
dragControls.addEventListener( 'dragend', function ( event: any ) {
if (commonStore.$state.currentPlayer === "p1" && commonStore.$state.flowIndex === 1) {
dragControls.enabled = true
event.object.position.y -= 0.04
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 handToSite = (data: any) => {
let sitePlane = scene.getObjectByName("己方战域Plane")
// console.log(data)
let userData = data.userData
if (userData.type === "怪兽") {
let meshes = sitePlane.children.filter((v: any) => v.name.indexOf("己方怪兽区") > -1 && v.userData.empty === true)
if (meshes.length > 0) {
let _mesh = null
let m1 = meshes.find((v: any) => v.name.indexOf(1) > -1)
let m2 = meshes.find((v: any) => v.name.indexOf(2) > -1)
let m3 = meshes.find((v: any) => v.name.indexOf(3) > -1)
if (m2) {
_mesh = m2
} else if (m1) {
_mesh = m1
} else if (m3) {
_mesh = m3
}
let p1_handGroup = scene.getObjectByName("p1_handGroup")
renderSiteCard(p1_handGroup, data, _mesh)
}
}
}
// 绘制场上卡牌
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") {
handRef.value.removeP1HandCard(oldMesh)
} else if (handGroup.name === "p2_handGroup") {
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)
// 创建伽马校正通道
// const gammaPass= new ShaderPass(GammaCorrectionShader)
// composer.addPass( gammaPass );
// const outlinePass = new OutlinePass(new THREE.Vector2( window.innerWidth, window.innerHeight ), scene, camera); // 模糊
// outlinePass.edgeStrength = 1.0; // 调整边缘强度
// outlinePass.edgeGlow = 1.0; // 边缘发光强度
// outlinePass.usePatternTexture = false; // 是否使用纹理
// outlinePass.visibleEdgeColor.set(0xffffff); // 设置边缘颜色
// outlinePass.hiddenEdgeColor.set(0x000000); // 设置隐藏边缘的颜色
// outlinePass.selectedObjects = [newMesh.children[0]]
// composer.addPass( outlinePass );
// console.log(123, newMesh)
}
// 下一阶段
const nextFlow = () => {
let flowIndex = JSON.parse(JSON.stringify(commonStore.$state.flowIndex))
flowIndex++
commonStore.updateFlowIndex(flowIndex)
}
// 回合结束
const nextRound = () => {
// 切换玩家
let player = commonStore.$state.currentPlayer
if (player === "p1") {
commonStore.updateCurrentPlayer("p2")
} else {
commonStore.updateCurrentPlayer("p1")
}
// 重置流程
commonStore.updateFlowIndex(0)
// 回合数增加
let round = JSON.parse(JSON.stringify(commonStore.$state.round))
round++
commonStore.updateRound(round)
}
// 取消
const onCancel = (data: any) => {
handRef.value.backPosition(data)
}
</script>
<style lang="scss" scoped>
.scene {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100vh;
}
.stage-box {
position: fixed;
top: 50%;
right: 4px;
z-index: 10;
margin-top: -20px;
display: flex;
align-items: center;
justify-content: center;
flex-wrap: wrap;
list-style: none;
// max-width: 200px;
// width: 40%;
height: 40px;
li {
// margin: 6px;
}
}
</style>
页面效果如下: