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

cocos做简单自动发射追踪子弹 切换敌人

在这里插入图片描述
先是获取敌人

this.huoqudiren();this.schedule(()=>{this.huoqudiren();},1);

如果敌人血量伪0 将敌人parent node下的血量伪0的敌人移除
const di=this.diren.children;

        const index = di.indexOf(this.guai);if(index!==-1){//console.log(di.splice(index,1));di.splice(index,1)console.log('....');//this.guai=di.pop();}

然后重新获取敌人

huoqudiren(){this.guai=this.findzuijindiren();//console.log(this.guai);if(this.guai==null){return;}let xue=this.guai.getComponent(enemyhit).getxue();if(xue<=0){console.log(this.guai.name);if(this.guai==null){return;}const di=this.diren.children;const index = di.indexOf(this.guai);if(index!==-1){//console.log(di.splice(index,1));di.splice(index,1)console.log('....');//this.guai=di.pop();}this.guai=this.findzuijindiren();console.log('huan',this.guai.name);}}

find最近敌人

findzuijindiren(){const di=this.diren.children;let zuijindiren=null;let zuijinjuli=Number.MAX_VALUE;for(let i=0;i<di.length;i++){//console.log(di[i].name);// 计算子弹与怪物之间的距离(正确的计算)let juli = Vec2.distance(this.node.position, di[i].position);if(juli<zuijinjuli){zuijinjuli=juli;zuijindiren=di[i];}}return zuijindiren;
}

计算脚本挂载node 角色位置
然后遍历敌人node下所有敌人node距离
返回这个敌人node

每秒发射子弹
this.schedule(()=>{
this.onezidan();
},1);
计算子弹 敌人距离然后实例化预制体子弹
将子弹添加到角色node的parent 如果添加到角色node 子弹会跟着角色动 不会追踪敌人
然后在fashezidan数组添加进实例化的子弹
给子弹开启碰撞检测

在update执行this.fashe(deltaTime);
在fashe 计算子弹 敌人方向向量然后归一

import { _decorator, Collider2D, Component, Contact2DType, director, instantiate, IPhysics2DContact, Node, NodePool, ParticleSystem2D, Prefab, RigidBody2D, Script, Sprite, TypeScript, v2, v3, Vec2, Vec3 } from 'cc';
import { enemyhit } from './enemyhit';
const { ccclass, property } = _decorator;@ccclass('fashe')
export class fashe extends Component {@property(Prefab)zdyuzhiti:Prefab=null;@property(Node)guai0:Node;zdsz:Node[]=[];@property(Node)diren:Node;fashezidansz:Node[]=[];guai=null;guaimap=new Map();guaisz=[];@property(Prefab)lizi:Prefab=null;// 标记需要延迟销毁的子弹bulletsToRemove: Node[] = [];danfahit:number=10;onLoad(){this.huoqudiren();this.schedule(()=>{this.huoqudiren();},1);for(let i=0;i<10;i++){const zd=instantiate(this.zdyuzhiti);//zd.setPosition(this.node.position);//this.node.parent.parent.addChild(zd);this.zdsz.push(zd);const fashe=this.node.getChildByName('gongji');fashe.active=false;}this.schedule(()=>{//this.sanzidan();},3);this.schedule(()=>{this.onezidan();},1);}update(deltaTime: number) {this.fashe(deltaTime);//console.log(this.zdsz.size());// 在update中处理子弹销毁,避免在物理回调中直接操作this.cleanInvalidBullets();// 新增:在处理完物理逻辑后,安全地销毁子弹this.processBulletRemoval();}// 清理无效的子弹cleanInvalidBullets() {for (let i = this.fashezidansz.length - 1; i >= 0; i--) {if (!this.fashezidansz[i].isValid) {this.fashezidansz.splice(i, 1);}}}//想象你在排队数人,数到谁没资格就让他出列。//如果从前往后数(正着数)://你数到第2个人,他没资格,你让他出列。
//他走了,后面所有人就都往前挪了一位。刚才的第3个人变成了第2个人。
//但你接下来会去数第3个人,就把刚刚挪上来的这个“新第2个人”给漏掉了,没检查他。
//如果从后往前数(倒着数)://你先数最后一个人。让他出列不影响你前面人的位置。
//接着你数倒数第二个,让他出列也不影响你还没数的、更前面的人。
//这样你数的每一个人,都是你还没检查过的,一个都不会漏。
//所以,代码里从后往前循环 (i--),就是为了在删除数组里的子弹时,不会把没检查的子弹给漏掉。 这是一种安全又省事的编程技巧。// 新增:处理待销毁的子弹processBulletRemoval() {// 处理所有待销毁的子弹while (this.bulletsToRemove.length > 0) {const bullet = this.bulletsToRemove.pop();if (bullet && bullet.isValid) {const index = this.fashezidansz.indexOf(bullet);if (index !== -1) {this.fashezidansz.splice(index, 1);}bullet.destroy(); // 在主循环中安全销毁}}}// 角度线性插值方法lerpAngle(from: number, to: number, speed: number): number {let difference = to - from;// 确保选择最短旋转方向while (difference > 180) difference -= 360;while (difference < -180) difference += 360;return from + difference * Math.min(speed, 1);}hqzd(){let zd:Node;if(this.zdsz.length>0){zd=this.zdsz.pop();}else{zd=instantiate(this.zdyuzhiti);}return zd;}onezidan(){if (!this.guai) return;// 计算与敌人的距离let juli = Vec2.distance(this.node.position, this.guai.position);if(juli<1000){
// 直接实例化新子弹
const zd = instantiate(this.zdyuzhiti);zd.name="danfa";
zd.setPosition(this.node.position.x+70,this.node.position.y-174);zd.active = true;
// 确保子弹有父节点if(!zd.parent){this.node.parent.parent.addChild(zd);
}this.fashezidansz.push(zd);
director.emit('fashezidan');
director.emit("danfa",10);
const collider = zd.getComponent(Collider2D);if (collider) {collider.on(Contact2DType.BEGIN_CONTACT, this.onBeginContact, this);}}}         huoqudiren(){this.guai=this.findzuijindiren();//console.log(this.guai);if(this.guai==null){return;}let xue=this.guai.getComponent(enemyhit).getxue();if(xue<=0){console.log(this.guai.name);if(this.guai==null){return;}const di=this.diren.children;const index = di.indexOf(this.guai);if(index!==-1){//console.log(di.splice(index,1));di.splice(index,1)console.log('....');//this.guai=di.pop();}this.guai=this.findzuijindiren();console.log('huan',this.guai.name);}}findzuijindiren(){const di=this.diren.children;let zuijindiren=null;let zuijinjuli=Number.MAX_VALUE;for(let i=0;i<di.length;i++){//console.log(di[i].name);// 计算子弹与怪物之间的距离(正确的计算)let juli = Vec2.distance(this.node.position, di[i].position);if(juli<zuijinjuli){zuijinjuli=juli;zuijindiren=di[i];}}return zuijindiren;
}fashe(deltaTime:number){if(this.guai==null){return;}for(let i=0;i<this.fashezidansz.length;i++){
// 计算子弹与怪物之间的距离(正确的计算)
let juli = Vec2.distance(this.fashezidansz[i].position, this.guai.position);// 只有在追踪距离内才进行追踪
if (juli < 1000) {this.fashezidansz[i].active=true;let direction = v2(this.guai.position.x - this.fashezidansz[i].position.x,this.guai.position.y - this.fashezidansz[i].position.y);direction.normalize();// 计算当前角度和目标角度let selfjiao = this.fashezidansz[i].angle;let guaijiao = Math.atan2(direction.y, direction.x);let jiao = guaijiao * 180 / Math.PI;// 平滑旋转角度let newjiao = this.lerpAngle(selfjiao, jiao, 70 * deltaTime);this.fashezidansz[i].angle = newjiao;// 根据新角度计算移动方向let r = newjiao * Math.PI / 180;let movex = Math.cos(r) * 700 * deltaTime;let movey = Math.sin(r) * 700 * deltaTime;// 应用移动this.fashezidansz[i].position = this.fashezidansz[i].position.add(v3(movex, movey, 0));
} else {// 如果不在追踪距离内,直线前进let r = this.fashezidansz[i].angle * Math.PI / 180;let movex = 700 ;let movey = 0;this.fashezidansz[i].active=false;//this.fashezidansz[i].position = this.fashezidansz[i].position.add(v3(movex, movey, 0));
}}}onBeginContact(selfCollider: Collider2D, otherCollider: Collider2D, contact: IPhysics2DContact |null){//console.log("ziji",selfCollider.node.name);//console.log("zhuang",otherCollider.node.name);const guaiwu=otherCollider.node;this.showlizi(selfCollider.node.position);guaiwu.getComponent(enemyhit).shoushang(this.danfahit);const bullet=selfCollider.node;if (bullet && bullet.isValid) {// 先从数组中移除const index = this.fashezidansz.indexOf(bullet);if (this.bulletsToRemove.indexOf(bullet) === -1) {this.bulletsToRemove.push(bullet);}let xue=otherCollider.node.getComponent(enemyhit).getxue();if(xue<=0){//console.log('huan',this.guai.name);}// 标记需要销毁的子弹,而不是立即销毁// 然后回收子弹}
}
showlizi(position:Vec3){const l=instantiate(this.lizi);l.setPosition(position);this.node.parent.parent.addChild(l);this.scheduleOnce(()=>{if(l.isValid){l.destroy();}},7);}}
http://www.dtcms.com/a/389567.html

相关文章:

  • C#知识学习-014(修饰符_3)
  • Linux 下逆向解析 VNC Server 密码文件为明文密码(逆向解析passwd)
  • Linux dma_resv机制原理、实现与应用详解
  • LangGraph 进阶学习
  • Alibaba Cloud Linux与 RHEL/CentOS版本对应关系
  • Python实现PDF文本与表格转换
  • 医疗行业数字化转型:构建安全合规、高效协同的智慧医疗文档管理新范式
  • 怎么看一个网址是否安全?
  • 【LLM】RAG架构如何重塑大模型
  • 企业级数据库管理实战(四):从 C/S 到 B/S架构,数据库管理工具的演进
  • 基于AI的PDF复杂表格结构识别与智能解析(方案1)
  • CS336第三课
  • 云蝠智能大模型呼叫对话延迟无限接近1秒
  • Datax-web安装 | 配置环境
  • 算法<java>——查找(顺序、二分、插值、分块、斐波那契)
  • Mysql杂志(十九)——InnoDB的索引结构
  • CrowdStrike推出AI驱动新工具 聚焦补丁管理与威胁情报短板
  • 收集飞花令碎片——C语言指针
  • MySQL 初识:架构定位与整体组成
  • 【开发者导航】规范驱动且开源的 AI 时代开发流程工具:GitHub Spec-Kit
  • 区块链加速器:Redis优化以太坊交易池性能方案
  • 资源分布的均衡性(Poisson Disk Sampling)探索
  • STM32开发(中断模式)
  • Qt QPieSlice详解
  • C++多线程编程
  • LangChain 父文档检索器:解决 “文档块匹配准” 与 “信息全” 的矛盾
  • COI实验室技能:基于几何光学的物空间与像空间的映射关系
  • springboot-security安全插件使用故障解析
  • 企业移动化管理(EMM)实战:如何一站式解决设备、应用与安全管控难题?
  • 高频面试题——深入掌握栈和队列的数据结构技巧