当前位置: 首页 > news >正文

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) // 己方HPconst p2HP = ref(4000) // 对方HPconst 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}// 更新己方HPfunction updateP1HP(data: any) {p1HP.value = data}// 更新对方HPfunction 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.valuelet _selectedTargetCard: any = selectedTargetCard.valueif (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.areaTypelet isP1 = areaType.indexOf("己方") > -1let graveyardGroup = nulllet graveyardGroupPos = new THREE.Vector3(0, 0, 0)let cards = []card.material.forEach((v: any) => {v.transparent = falsev.opacity = 1v.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 = nullselectedTargetCard.value = null} else if (selectedCard.value) { // 如果只存在selectedCard// 直接攻击let _selectedCard: any = selectedCard.valueconsole.log(333, _selectedCard)if (selectedCard.value.name === "攻击力") {_selectedCard = _selectedCard.value.parent}let areaType = _selectedCard.userData.areaTypelet isP1 = areaType.indexOf("己方") > -1let 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.ATKif (p2HP < 0) {p2HP = 0}commonStore.updateP2HP(p2HP)} else {let p1HP = JSON.parse(JSON.stringify(commonStore.$state.p1HP))p1HP -= _selectedCard.userData.ATKif (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("己方") > -1let mesh = nullif (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 }

页面效果如下:

相关文章:

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

首先将双方玩家的HP存入store中&#xff0c;stores/common.ts代码如下&#xff1a; import { ref, computed } from vue import { defineStore } from piniaexport const useCommonStore defineStore(common, () > {const _font ref() // 字体const p1HP ref(4000) // 己…...

Linux内核err.h文件分析

在阅读和编写内核相关的代码时&#xff0c;经常会看到IS_ERR、ERR_PTR等函数。这些函数在内核头文件的err.h中。以我服务器的代码为例&#xff0c;内核版本为5.15。 这个文件的代码如下&#xff1a; /* SPDX-License-Identifier: GPL-2.0 */ #ifndef _LINUX_ERR_H #define _L…...

Qt 富文本处理 (字体颜色大小加粗等)

Qt中支持HTML的控件有textEdit 、label 、textBrowser 。 接口&#xff1a;setHtml("Qt"); toHtml(). 文本样式设置 : 可分字设置 &#xff0c;主要使用QTextCharFormat类进行文本样式设置。 示例&#xff1a; QTextCharFormat fmt; //粗体 fmt.setFontWeight…...

消息队列的七种经典应用场景

在笔者心中&#xff0c;消息队列&#xff0c;缓存&#xff0c;分库分表是高并发解决方案三剑客。 在职业生涯中&#xff0c;笔者曾经使用过 ActiveMQ 、RabbitMQ 、Kafka 、RocketMQ 这些知名的消息队列 。 这篇文章&#xff0c;笔者结合自己的真实经历&#xff0c;和大家分享…...

uniapp 微信小程序 canvas 手写板文字重复倾斜水印

核心逻辑 先将坐标系中心点通过ctx.translate(canvasw / 2, canvash / 2) 平移到canvas 中心&#xff0c;再旋转设置水印 假如不 translate 直接旋转&#xff0c;则此时的旋转中心为左上角原点&#xff0c;此时旋转示意如图所示 当translate到中心点之后再旋转&#xff0c;此…...

JavaScript如何制作轮播图

在JavaScript中实现轮播图可以通过多种方式&#xff0c;但最常见的方式是使用数组来存储图片&#xff0c;然后使用setInterval函数定期更改显示的图片。下面是一个简单的例子&#xff1a; 首先&#xff0c;你需要在HTML中设置一些用于显示图片的<img>标签&#xff0c;以…...

【面试经典150 | 动态规划】零钱兑换

文章目录 Tag题目来源解题思路方法一&#xff1a;动态规划 写在最后 Tag 【动态规划】【数组】 题目来源 322. 零钱兑换 解题思路 方法一&#xff1a;动态规划 定义状态 dp[i] 表示凑成总金额的最少硬币个数。 状态转移 从小到大枚举要凑成的金额 i&#xff0c;如果当前…...

什么是防火墙,部署防火墙有什么好处?

与我们的房屋没有围墙或界限墙一样&#xff0c;没有防护措施的计算机和网络将容易受到黑客的入侵&#xff0c;这将使我们的网络处于巨大的风险之中。因此&#xff0c;就像围墙保护我们的房屋一样&#xff0c;虚拟墙也可以保护和安全我们的设备&#xff0c;使入侵者无法轻易进入…...

学习鸿蒙基础(10)

目录 一、轮播组件 Swiper 二、列表-List 1、简单的List 2、嵌套的List 三、Tabs容器组件 1、系统自带tabs案例 2、自定义导航栏&#xff1a; 一、轮播组件 Swiper Entry Component struct PageSwiper {State message: string Hello Worldprivate SwCon: SwiperControl…...

阿里云对象存储OSS入门

阅读目录 一、阿里云OSS的使用 1、OSS是什么&#xff1f;2、OSS的使用 二、阿里云OSS的使用三、图床的搭建四&#xff1a;图床绑定阿里云OSS 编写不易&#xff0c;如果我的文章对你有帮助的话&#xff0c;麻烦小伙伴还帮忙点个赞再走&#xff01; 如果有小伙伴觉得写的啰嗦&a…...

[幻灯片]软件需求设计方法学全程实例剖析-03-业务用例图和业务序列图

DDD领域驱动设计批评文集 做强化自测题获得“软件方法建模师”称号 《软件方法》各章合集 pdf已上传至本号的CSDN资源&#xff0c;或到以下地址下载&#xff1a; http://umlchina.com/training/umlchina_03_bm.pdf...

ctfshow-web入门-xxe

什么是xxe&#xff1f; XXE&#xff0c;全称XML External Entity Injection&#xff0c;即XML外部实体注入。这是一种针对应用程序解析XML输入类型的攻击。当包含对外部实体的引用的XML输入被弱配置的XML解析器处理时&#xff0c;就会发生这种攻击。这种攻击通过构造恶意内容&…...

Docker数据卷挂载

一、容器与数据耦合的问题: 数据卷是虚拟的&#xff0c;不真实存在的&#xff0c;它指向文件中的文件夹 &#xff0c;属主机文件系统通过数据卷和容器数据进行联系&#xff0c;你改变我也改变。 解决办法&#xff1a; 对宿主机文件系统内的文件进行修改&#xff0c;会立刻反应…...

QT_day4:对话框

1、完善对话框&#xff0c;点击登录对话框&#xff0c;如果账号和密码匹配&#xff0c;则弹出信息对话框&#xff0c;给出提示”登录成功“&#xff0c;提供一个Ok按钮&#xff0c;用户点击Ok后&#xff0c;关闭登录界面&#xff0c;跳转到其他界面 如果账号和密码不匹配&…...

矢量数据库:连接人工智能应用程序的数据复杂性与可用性的桥梁

关注我的公众号&#xff1a;Halo咯咯 简介 矢量数据库是一种专门设计的数据库&#xff0c;专注于高效地存储、管理和操作矢量数据。与传统数据库处理标量值&#xff08;如数字、字符串、日期&#xff09;不同&#xff0c;矢量数据库针对的是那些表现为多维数据点的向量&#xf…...

docker:can’t create unix socket /var/run/docker.sock: is a directory

docker:can’t create unix socket /var/run/docker.sock: is a directory 原因&#xff1a;docker.sock不能创建 解决方式&#xff1a; rm -rf /var/run/docker.sock 然后重新启动docker Docker是一种相对使用较简单的容器&#xff0c;我们可以通过以下几种方式获取信息&…...

Qt 图形视图 /图形视图框架坐标系统的设计理念和使用方法

文章目录 概述Qt 坐标系统图形视图的渲染过程Item图形项坐标系Scene场景坐标系View视图坐标系map坐标映射场景坐标转项坐标视图坐标转图形项坐标图形项之间的坐标转换 其他 概述 The Graphics View Coordinate System 图形视图坐标系统是Qt图形视图框架的重要组成部分&#xf…...

视频号小店类目资质如何申请?新手看一遍就懂了!

我是电商珠珠 大家在视频号小店后台新增商品的时候&#xff0c;需要先完成类目资质的申请&#xff0c;通过后才可以上架相关商品。 而类目资质分为普通类目和特殊类目&#xff0c;如果你所上架的商品属于开放类目&#xff0c;那么就去按照普通类目资质去申请。 如果是定向准…...

整合SpringSecurity+JWT实现登录认证

一、关于 SpringSecurity 在 Spring Boot 出现之前&#xff0c;SpringSecurity 的使用场景是被另外一个安全管理框架 Shiro 牢牢霸占的&#xff0c;因为相对于 SpringSecurity 来说&#xff0c;SSM 中整合 Shiro 更加轻量级。Spring Boot 出现后&#xff0c;使这一情况情况大有…...

C# Onnx Yolov9 Detect 物体检测

目录 介绍 效果 项目 模型信息 代码 下载 C# Onnx Yolov9 Detect 物体检测 介绍 yolov9 github地址&#xff1a;https://github.com/WongKinYiu/yolov9 Implementation of paper - YOLOv9: Learning What You Want to Learn Using Programmable Gradient Information…...

基于Ollama与Stable Diffusion的Discord AI机器人本地部署指南

1. 项目概述&#xff1a;一个能聊能画的Discord AI机器人 最近在折腾一个挺有意思的玩意儿&#xff1a;一个部署在自己电脑上的Discord机器人&#xff0c;它不仅能像ChatGPT一样跟你聊天&#xff0c;还能根据你的描述生成图片。这个项目的核心&#xff0c;是把两个当下很火的开…...

libhv实战:300行构建C++异步RPC框架,集成Protobuf与evpp

1. 为什么需要C异步RPC框架 在微服务架构盛行的今天&#xff0c;服务间的通信效率直接决定了系统整体性能。传统同步RPC调用就像打电话&#xff0c;必须等对方接听才能开始对话&#xff0c;而异步RPC更像是发微信&#xff0c;发完消息就可以去做其他事情&#xff0c;等对方回复…...

零成本搭建OpenAI API代理:基于Cloudflare Workers的稳定访问方案

1. 项目概述与核心价值 最近在折腾AI应用开发的朋友&#xff0c;估计都绕不开一个头疼的问题&#xff1a;OpenAI的官方API接口在国内网络环境下访问起来不太稳定&#xff0c;时不时就给你来个连接超时或者直接被墙。我自己在做一些个人项目和小工具时&#xff0c;也经常被这个问…...

3分钟掌握Windows任务栏投资助手:打造你的桌面股票监控中心

3分钟掌握Windows任务栏投资助手&#xff1a;打造你的桌面股票监控中心 【免费下载链接】TrafficMonitorPlugins 用于TrafficMonitor的插件 项目地址: https://gitcode.com/gh_mirrors/tr/TrafficMonitorPlugins 想在Windows任务栏上实时监控股票行情&#xff0c;又不想…...

Taotoken用量看板与成本管理功能的实际使用体验

&#x1f680; 告别海外账号与网络限制&#xff01;稳定直连全球优质大模型&#xff0c;限时半价接入中。 &#x1f449; 点击领取海量免费额度 Taotoken用量看板与成本管理功能的实际使用体验 对于需要持续调用大模型API的项目而言&#xff0c;成本的可观测与可控性是管理中的…...

技术生态依赖的实质与破局:从Android到自主可控的实践路径

1. 项目背景与核心议题解析最近在整理行业资料时&#xff0c;翻到一篇2013年的旧文&#xff0c;讨论的是当时中国工信部对国内移动产业过度依赖Android系统的担忧。虽然时过境迁&#xff0c;但文中提到的“技术自主可控”与“全球生态融入”之间的张力&#xff0c;在今天看来依…...

3分钟搞定浏览器二维码:Chrome QRCode插件的终极使用秘籍

3分钟搞定浏览器二维码&#xff1a;Chrome QRCode插件的终极使用秘籍 【免费下载链接】chrome-qrcode :zap: A Chrome plugin to Genrate QRCode of URL / Text, or Decode the QRcode in website. 一个Chrome浏览器插件&#xff0c;用于生成当前URL或者选中内容的二维码&#…...

AI写作净化器:识别与消除AI文本痕迹的实用指南

1. 项目概述&#xff1a;为什么我们需要一个“AI写作净化器”&#xff1f; 如果你和我一样&#xff0c;每天都要和AI助手打交道&#xff0c;无论是用它写邮件、生成报告&#xff0c;还是草拟技术文档&#xff0c;那你一定对那种“AI味儿”深有体会。那种感觉就像喝了一杯过度调…...

三维扫描平民化实战:从手机APP到高精度重建全流程指南

1. 项目概述&#xff1a;当三维扫描走下神坛几年前&#xff0c;如果你想获取一个真实物体的三维数字模型&#xff0c;那通常意味着你需要联系一家专业的三维扫描服务公司&#xff0c;支付一笔不菲的费用&#xff0c;然后等待专业人士用一台价格堪比一辆豪华轿车的设备&#xff…...

在ubuntu上使用nodejs通过taotoken统一调用多模型api

&#x1f680; 告别海外账号与网络限制&#xff01;稳定直连全球优质大模型&#xff0c;限时半价接入中。 &#x1f449; 点击领取海量免费额度 在 Ubuntu 上使用 Node.js 通过 Taotoken 统一调用多模型 API 基础教程类&#xff0c;指导 Ubuntu 上的 Node.js 开发者如何利用 T…...