利用对象池实现子弹的回收
当然,以下是对你所提供的代码的逐行注释。这些注释主要用于解释代码的功能和目的:
typescript复制代码
// 使用 Cocos Creator 的 ccclass 装饰器,声明一个名为 "GameRoot" 的类,它继承自 Component。 | |
@ccclass("GameRoot") | |
export class GameRoot extends Component { | |
// 使用 property 装饰器,声明 bgNode 属性,类型为 Node。这通常表示游戏的背景节点。 | |
@property(Node) bgNode: Node; | |
// 玩家节点。 | |
@property(Node) player: Node; | |
// 子弹的根节点,用于存放生成的子弹。 | |
@property(Node) bulletsRoot: Node; | |
// 使用 Prefab 类型声明的子弹预制体属性。Prefab 是预制体的缩写,通常用于存储游戏对象的预设配置。 | |
@property(Prefab) bulletPrefab: Prefab; | |
// 对象池,用于存储可用的子弹节点。初始化为空数组。 | |
bulletsPool = []; | |
// start 方法是 Cocos Creator 组件的生命周期方法,当组件开始运行时会自动调用此方法。 | |
start() { | |
this.openTouchMoveEvent(); // 开启触摸移动事件,使玩家节点能够响应触摸操作。 | |
this.startCreateBullet(); // 开始创建子弹。 | |
this.createBulletsPool(); // 初始化子弹对象池。 | |
} | |
// 定时调用 createOneBullet 方法,每0.2秒调用一次。 | |
startCreateBullet() { | |
this.schedule(this.createOneBullet, 0.2); | |
} | |
// 创建子弹对象池,生成30个子弹节点并加入到对象池中。 | |
createBulletsPool() { | |
for (let i = 0; i < 30; i++) { | |
const bullet = instantiate(this.bulletPrefab); // 实例化子弹预制体。 | |
bullet.setParent(this.bulletsRoot); // 将生成的子弹节点设置到子弹根节点下。 | |
bullet.active = false; // 设置为不活跃状态,表示当前子弹未被使用。 | |
this.bulletsPool.push(bullet); // 将子弹加入对象池。 | |
} | |
} | |
// 从对象池中取出一个子弹,并设置其位置。若对象池为空,则不执行任何操作。 | |
createOneBullet() { | |
if (this.bulletsPool.length > 0) { | |
const bullet = this.bulletsPool.pop(); // 从对象池中取出一个子弹。 | |
bullet.active = true; // 设置为活跃状态,表示当前子弹被使用。 | |
bullet.setPosition(this.player.position.x, this.player.position.y + 80); // 设置子弹的位置。 | |
} | |
} | |
// 开启触摸移动事件,当玩家节点被拖动时,会触发此事件。 | |
openTouchMoveEvent() { | |
this.player.on(Node.EventType.TOUCH_MOVE, this.onTouchMove, this); | |
} | |
// 触摸移动事件的回调函数,当玩家节点被拖动时,会更新玩家的位置。 | |
onTouchMove(event: EventTouch) { | |
this.player.setWorldPosition( | |
event.getUILocation().x, // 更新玩家的世界位置。 | |
event.getUILocation().y, // 同上。 | |
0 // z轴位置为0。 | |
); | |
} | |
// update 方法会在每一帧被调用,用于更新游戏逻辑。deltaTime 是上一帧到当前帧的时间差。 | |
update(deltaTime: number) { | |
// 此循环用于更新背景节点的子节点位置。实现了一种背景滚动的效果。 | |
for (let i = 0; i < this.bgNode.children.length; i++) { | |
let childNode = this.bgNode.children[i]; // 获取背景节点的子节点。 | |
childNode.setPosition( // 更新子节点的位置。 | |
childNode.position.x, // x轴位置保持不变。 | |
childNode.position.y - 50 * deltaTime // y轴位置根据时间差进行移动。 | |
); | |
let p = childNode.position.y; // 获取子节点的y轴位置。 | |
if (p < -850) { // 如果y轴位置小于-850,则进行重置操作,实现背景的无缝滚动。 | |
p += 852 * 2; // 重置y轴位置。 | |
} | |
childNode.setPosition(this.bgNode.position.x, p); // 重新设置子节点的位置。 | |
} | |
// 此循环用于更新所有子弹的位置, |
// 并检查是否需要回收子弹到对象池。 | |
for (let i = 0; i < this.bulletsRoot.children.length; i++) { | |
const bullet = this.bulletsRoot.children[i]; // 获取当前正在处理的子弹节点。 | |
const x = bullet.position.x; // 获取子弹的x轴位置。 | |
const y = bullet.position.y + 200 * deltaTime; // 计算子弹新的y轴位置,根据时间差进行移动。 | |
bullet.setPosition(x, y); // 更新子弹的位置。 | |
// 如果子弹的y轴位置大于600,表示子弹已经飞出屏幕,可以进行回收操作。 | |
if (y > 600) { | |
bullet.active = false; // 设置子弹为不活跃状态。 | |
this.bulletsPool.push(bullet); // 将子弹回收到对象池,以供后续复用。 | |
} | |
} |
}