import { _decorator, Component, Sprite, SpriteFrame, UITransform, Size, CircleCollider2D, Contact2DType, IPhysics2DContact, RigidBody2D, Vec2, Node } from 'cc'; import { FRUITS, MAX_LEVEL } from './FruitConfig'; import { GameManager } from './GameManager'; const { ccclass, property } = _decorator; @ccclass('Fruit') export class Fruit extends Component { @property level = 1; // 1..MAX_LEVEL @property(Sprite) sprite!: Sprite; game!: GameManager; collider!: CircleCollider2D; body!: RigidBody2D; // 防止同一对重复合成 merging = false; removed = false; init(level: number, spriteFrame: SpriteFrame, game: GameManager) { this.level = level; this.game = game; if (!this.sprite) this.sprite = this.getComponent(Sprite)!; this.sprite.spriteFrame = spriteFrame; const def = FRUITS[this.level - 1]; const ui = this.getComponent(UITransform)!; ui.setContentSize(new Size(def.radius * 2, def.radius * 2)); this.collider = this.getComponent(CircleCollider2D)!; this.collider.radius = def.radius; this.body = this.getComponent(RigidBody2D)!; this.body.enabled = true; this.merging = false; this.removed = false; } onEnable() { const col = this.getComponent(CircleCollider2D); if (col) col.on(Contact2DType.BEGIN_CONTACT, this.onBeginContact, this); } onDisable() { const col = this.getComponent(CircleCollider2D); if (col) col.off(Contact2DType.BEGIN_CONTACT, this.onBeginContact, this); } private onBeginContact(selfCol: CircleCollider2D, otherCol: CircleCollider2D, _contact: IPhysics2DContact | null) { if (this.removed || this.merging) return; const otherNode = otherCol.node as Node; const otherFruit = otherNode.getComponent(Fruit); if (!otherFruit || otherFruit.removed || otherFruit.merging) return; // 仅同级可合成,且不能超过最大级 if (otherFruit.level !== this.level || this.level >= MAX_LEVEL) return; // 为避免两者都合成,使用 uuid 决定触发者(只让“较小”的触发) if (this.node.uuid > otherNode.uuid) return; this.merging = true; otherFruit.merging = true; // 合成到下一级 const nextLevel = this.level + 1; const wpA = this.node.worldPosition; const wpB = otherNode.worldPosition; const mid = wpA.clone().add(wpB).multiplyScalar(0.5); this.game.spawnMerged(nextLevel, mid, this, otherFruit); } }