import { _decorator, Component, Node, Sprite, SpriteFrame, resources, Prefab, instantiate, UITransform, Vec2, Vec3, RigidBody2D, macro } from 'cc'; const { ccclass, property } = _decorator; @ccclass('WeaponRandomSpawner') export class WeaponRandomSpawner extends Component { /** * Pellet prefab used as bullet. Drag the Pellet.prefab into this slot in the editor. */ @property({ type: Prefab }) public pelletPrefab: Prefab | null = null; /** * Time interval (seconds) between two shots. */ @property public fireInterval: number = 1.0; /** Cached weapon sprite component (WeaponBlock/B1/Weapon) */ private _weaponSprite: Sprite | null = null; /** The sprite frame chosen randomly at scene start */ private _selectedFrame: SpriteFrame | null = null; onLoad() { // Locate the Weapon sprite component inside the prefab hierarchy const b1Node: Node | null = this.node.getChildByName('B1'); if (!b1Node) { console.error('[WeaponRandomSpawner] Cannot find child node "B1"'); return; } const weaponNode: Node | null = b1Node.getChildByName('Weapon'); if (!weaponNode) { console.error('[WeaponRandomSpawner] Cannot find grand-child node "Weapon" under B1'); return; } this._weaponSprite = weaponNode.getComponent(Sprite); if (!this._weaponSprite) { console.error('[WeaponRandomSpawner] Sprite component missing on Weapon node'); return; } // Load all sprite frames under resources/images/PlantsSprite at runtime resources.loadDir('images/PlantsSprite', SpriteFrame, (err, assets) => { if (err) { console.error('[WeaponRandomSpawner] Failed to load PlantsSprite resources:', err); return; } if (!assets || assets.length === 0) { console.warn('[WeaponRandomSpawner] No sprite frames found in images/PlantsSprite'); return; } // Pick one sprite frame randomly and apply to weapon this._selectedFrame = assets[Math.floor(Math.random() * assets.length)]; if (this._weaponSprite) { this._weaponSprite.spriteFrame = this._selectedFrame; } }); } start() { // Start auto-fire schedule this.schedule(this._fire.bind(this), this.fireInterval); } /** * Instantiate a bullet prefab, copy the weapon sprite frame to it (scaled to half size) * and give it an upward velocity. */ private _fire() { if (!this.pelletPrefab || !this._selectedFrame) { return; // Not ready yet } const bullet: Node = instantiate(this.pelletPrefab); // Add to the same scene, at world position of the weapon muzzle (current node) this.node.scene?.addChild(bullet); bullet.setWorldPosition(this.node.worldPosition); // Set bullet sprite frame const bulletSprite = bullet.getComponent(Sprite); if (bulletSprite) { bulletSprite.spriteFrame = this._selectedFrame; } // Match bullet size to half of weapon sprite size const weaponUi = this._weaponSprite?.node.getComponent(UITransform); const bulletUi = bullet.getComponent(UITransform); if (weaponUi && bulletUi) { const size = weaponUi.contentSize; bulletUi.setContentSize(size.width * 0.5, size.height * 0.5); } else { // Fallback: scale the whole node bullet.setScale(this.node.scale.x * 0.5, this.node.scale.y * 0.5, 1); } // Give the bullet an upward velocity if it has a RigidBody2D component const rb = bullet.getComponent(RigidBody2D); if (rb) { rb.linearVelocity = new Vec2(0, 600); } } }