敌人管理

大家好!下面是敌人如何被调度、移动以及戏剧性离场的,以及从游戏代码中摘录的几个真实片段。

调度波次

敌人出现被存储为 enemy-type 和时间对。例如,游戏设置会排队一个小绸带波次:

queueEnemyWave(entityType.ENEMY_RIBBON, 100, 110, 120, 130, 140);

助手将每个已调度的出现添加到生成表:

private void queueEnemyWave(entityType type, int... spawnTimes) {
for (int spawnTime : spawnTimes) {
game.addEnemySpawn(spawnTime, type);
}
}

游戏时钟使用帧为单位。当 spawn 到达时,如果仍有活跃 enemies,spawner 会等待,因此一波不会立即叠加在另一波之上:

if (!enemyList.isEmpty()) {
return;
}

在选定的 spawn 时间,玩家等级决定生成的 enemies 数量:

int spawnMultiplier = playerLevel + 1 < 1 ? 1 : playerLevel + 1;

障碍块拥有自己的形成逻辑,包括随机的组大小和颜色。Boss 是特殊情况,它从独立的阶段计时器触发。

不同移动,共享更新循环

敌人共享位置、速度、血量和动画等核心实体数据,但其类型决定其行为。例如,绸带敌人会从一个小型移动助手获取位置:

public static Position calculateEnemyPosition(float x, float speed, float worldHeight) {
float nextX = x - .3f * speed;
float nextY = 30 * MathUtils.sin(.1f * nextX) + worldHeight / 2f;
return new Position(nextX, nextY);
}

The enemy update loop 为绸带敌人调用该助手,而追踪器、射击者和障碍物则走不同的路径。追踪器追踪玩家,且几种敌人类型会定时射击。例如,追踪器会将其射线对准玩家:

case entityType.ENEMY_TRACKER:
game.getEnemyBulletList().add(game.bulletFactory(
entityType.ENEMY_BULLET,
e.x,
e.y,
angleToPlayer(e, player)
));
break;

打击、失败与清理

当玩家子弹与敌人重叠时,游戏会检查敌人是否完全在屏幕上并且已经过了简短的击中冷却时间后才应用伤害:

if (e.collisionRectangle.overlaps(f.collisionRectangle)
&& e.scale >= 1f
&& e.invincibilityTimer >= 5f) {
e.invincibilityTimer = 0;
e.health -= f.damage;
releaseFromList(playerBulletList, j);
entityEnemyDeathCheck(
game.getPowerUPRedList(),
game.getPowerUPBlueList(),
game.getPowerUPGreenList(),
game.getEnemyList(),
game.getExplosionsList(),
e,
false
);
}

死亡处理器负责反馈:爆炸、分数和击杀计数更新,以及根据敌人类型掉落硬币或 power-up。被击败的实体会被排队删除,并在活动更新工作完成后清理,从而保持实体列表安全可处理。