消消方块阵换皮表情
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

169 lines
5.9 KiB

import { _decorator, CCBoolean, CCFloat, Component, instantiate, Node, NodePool, Prefab, UITransform, v3 } from 'cc';
import { GBundle } from '../../game/ConfigRes';
import { atgSkill } from './atgSkill';
import { gaoyaguo } from './gaoyaguo';
import { GEvent } from 'db://assets/mx/module/event/GEvent';
const { ccclass, property } = _decorator;
@ccclass('zidanScript')
export class zidanScript extends Component {
//子弹内存池
@property(Prefab)
zidanPrefab: Prefab = null;
zidanPool: NodePool = null;
bulletSpeed: number = 700;
_dt: number = 0;
deltaTime: number = 0.016;
/** jiedianIndex==3 时:子弹世界坐标 Y 需接近主角才做命中判定,避免门廊区被超大 UITransform 误杀 */
@property(CCFloat)
playerHitWorldYOffset: number = 180;
@property(CCBoolean)
debugBulletMove: boolean = false;
/** 子弹世界坐标越界回收的边界(避免飞出屏幕后一直存在)。按设计分辨率 750x1600 做默认值,可在编辑器调。 */
@property(CCFloat)
recycleWorldHalfWidth: number = 750;
@property(CCFloat)
recycleWorldHalfHeight: number = 1600;
@property(CCFloat)
recycleWorldPadding: number = 300;
private _debugAcc = 0;
protected onDestroy(): void {
if (this.zidanPool) this.zidanPool.clear()
}
protected start(): void {
this.zidanPool = new NodePool()
//添加100个子弹
for (let i = 0; i < 100; i++) {
let zidan = instantiate(this.zidanPrefab)
this.zidanPool.put(zidan)
}
}
//获取子弹
getZidan(): Node {
if (this.zidanPool.size() > 0) {
}else{
let zidan = instantiate(this.zidanPrefab)
this.zidanPool.put(zidan)
}
return this.zidanPool.get()
}
//放入子弹
putZidan(zidan: Node) {
zidan.removeFromParent();
this.zidanPool.put(zidan)
}
protected update(dt: number): void {
if(gaoyaguo.Instance.isGameOver){
return
}
const children = this.node.children;
const hitList: Node[] = [];
/** 飞过主角仍未碰到主角盒,只回收不计分(避免与 qiang 超大 AABB 误杀整屏子弹) */
const missRecycleList: Node[] = [];
const g = gaoyaguo.Instance;
const guoTrans = g?.gaoyaguo_guo?.getComponent(UITransform) ?? null;
const guoBox = guoTrans ? guoTrans.getBoundingBoxToWorld() : null;
//const zhujueTrans = g?.zhujueNode?.getComponent(UITransform) ?? null;
// const zhujueBox = zhujueTrans ? zhujueTrans.getBoundingBoxToWorld() : null;
this._debugAcc += dt;
const doDbg = this.debugBulletMove && this._debugAcc >= 1;
if (doDbg) this._debugAcc = 0;
let sampleChild: Node | null = null;
children.forEach((child)=>{
if (doDbg && !sampleChild) sampleChild = child;
if(!child.active){
return
}
const skill = child.getComponent(atgSkill);
if (skill?.ignoreContactFrames > 0) {
skill.ignoreContactFrames--;
if (skill.ignoreContactFrames <= 0) {
skill.ignoreDoorUuid = null;
}
}
const dir = skill?.moveDir ?? v3(0, 1, 0);
const p = child.position;
child.setPosition(
p.x + dir.x * this.bulletSpeed * dt,
p.y + dir.y * this.bulletSpeed * dt,
p.z
);
// 世界坐标越界回收(含 padding)
const wp = child.worldPosition;
if (
Math.abs(wp.x) > this.recycleWorldHalfWidth + this.recycleWorldPadding ||
Math.abs(wp.y) > this.recycleWorldHalfHeight + this.recycleWorldPadding
) {
missRecycleList.push(child);
return;
}
// jiedianIndex == 2:子弹命中高压锅才触发回收/扣血(否则会导致“子弹一生成就被回收”)
if (g?.jiedianIndex === 2 && guoBox) {
const bulletTrans = child.getComponent(UITransform);
if (bulletTrans) {
const bulletBox = bulletTrans.getBoundingBoxToWorld();
if (bulletBox.intersects(guoBox)) {
hitList.push(child);
}
}
}else if(g?.jiedianIndex == 3){
// 只用主角盒判定「命中计分」;左右墙 UITransform 常过大,若参与 OR 会导致整路子弹同一帧进 hitList(length 上百)
}
})
if (doDbg) {
const s = sampleChild?.getComponent(atgSkill);
console.log('[zidanScript] tick', {
jiedianIndex: g?.jiedianIndex,
children: children.length,
sample: sampleChild?.name ?? null,
sampleLocal: sampleChild ? { x: sampleChild.position.x, y: sampleChild.position.y } : null,
sampleWorld: sampleChild ? { x: sampleChild.worldPosition.x, y: sampleChild.worldPosition.y } : null,
sampleDir: s ? { x: s.moveDir.x, y: s.moveDir.y } : null,
bulletSpeed: this.bulletSpeed,
});
}
// 统一处理命中,避免遍历 children 时修改层级
if (hitList.length > 0) {
for (const child of hitList) {
this.putZidan(child);
}
if (g?.jiedianIndex == 2) {
GEvent.Ins.emit(GEvent.hitGaoyaguo, hitList.length, hitList[0]);
}
}
if (missRecycleList.length > 0) {
console.log('missRecycleList', missRecycleList.length)
for (const child of missRecycleList) {
this.putZidan(child);
}
}
}
}