refactor(rogue): 重构关卡刷怪与流程为一关一局模式

1.  将原10小节/关改为5小节/关,固定节类型为1-3普通节、4精英节、5Boss节
2.  调整刷怪逻辑:普通节3只小怪立即全刷,移除定时分批刷怪
3.  统一怪物入场方式为从右侧屏幕外贴地跑入,移除高空掉落动画
4.  移除小节间结算弹窗,改为自动连战,节间仅播放背景滚动过渡
5.  简化结算逻辑,仅保留通关/失败两种结算类型,移除小节胜利分支
6.  重构关卡进度存储,仅保存章节关卡,小节恒从1开始
This commit is contained in:
panFD
2026-09-12 19:03:48 +08:00
parent d951896799
commit 1b2545deec
5 changed files with 196 additions and 260 deletions

View File

@@ -3,8 +3,8 @@
* @description 关卡系统配置(章节-关-节三级结构)
*
* 设计要点:
* - 1 章 = 10 关,每关 = 10 小节,共 100 个小节
* - 第 5 关为精英关,第 10 关为 Boss 关,其余为普通关
* - 1 章 = 10 关,每关 = 5 小节(一关一局,节间自动推进),共 50 个小节
* - 每关节点固定:1~3 节普通(3 小怪)、第 4 节精英(3 精英)、第 5 节 Boss(1 Boss + 2 小怪)
* - 怪物等级 = 关卡号(1-1 的怪为 Lv1,1-5 的怪为 Lv5)
* - 怪物属性 = 基础 × 开局系数 × (1 + 成长斜率 × (lv-1)) × 类型倍率
*
@@ -26,26 +26,32 @@ export const MON_GROW_SLOPE = 0.05;
export const ELITE_MUL = 1.5;
/** Boss 属性倍率:同级普通怪的 3.0 倍(精英 × 2) */
export const BOSS_MUL = 3.0;
/** 普通关小怪数量 */
export const NORMAL_MON_COUNT = 9;
/** 普通关开局立即刷出数量 */
/** 每关小节总数(一关一局,节间自动推进) */
export const SECTIONS_PER_STAGE = 5;
/** 精英节号(每关第 4 节为精英节) */
export const ELITE_SECTION = 4;
/** Boss 节号(每关第 5 节为 Boss 节,即末节) */
export const BOSS_SECTION = 5;
/** 普通节小怪数量(一关一局压缩后单节 3 只) */
export const NORMAL_MON_COUNT = 3;
/** 普通节开局立即刷出数量(3 只全部立即刷出) */
export const NORMAL_FIRST_SPAWN = 3;
/** 普通关后续刷怪间隔(秒):前 3 只立即刷,后续每 2s 刷 1 只 */
/** 普通节后续刷怪间隔(秒):保留配置位(3 只全立即刷,当前无后续批次) */
export const NORMAL_SPAWN_INTERVAL = 2;
/** 精英关精英数量 */
/** 精英节精英数量 */
export const ELITE_COUNT = 3;
/** Boss 关精英数量 */
/** Boss 节护卫小怪数量 */
export const BOSS_ELITE_COUNT = 2;
/** Boss 关 Boss 延迟刷出时间(秒) */
/** Boss 节 Boss 延迟刷出时间(秒) */
export const BOSS_DELAY = 1;
// ======================== 类型定义 ========================
/** 小节类型 */
export enum SectionType {
Normal = 0, // 普通关:9 小怪
Elite = 1, // 精英关:3 精英
Boss = 2, // Boss 关:1 Boss + 2 精英
Normal = 0, // 普通节:3 小怪
Elite = 1, // 精英节:3 精英
Boss = 2, // Boss 节:1 Boss + 2 小怪
}
/** 小节配置 */
@@ -62,13 +68,13 @@ export interface SectionConfig {
monTypes?: MonType[];
}
/** 大关配置(1-1 ~ 1-10) */
/** 大关配置(1-1 ~ 1-10),每关 SECTIONS_PER_STAGE 个小节 */
export interface StageConfig {
/** 章节号 */
chapter: number;
/** 关卡号 1~10 */
stage: number;
/** 10 个小节 */
/** 小节列表(长度 = SECTIONS_PER_STAGE) */
sections: SectionConfig[];
}
@@ -122,40 +128,40 @@ export function getMonsterLv(stage: number): number {
}
/**
* 判断是否为精英关
* @param stage 关卡号(1~10)
* 判断是否为精英节(每关第 ELITE_SECTION 节)
* @param section 小节号(1~SECTIONS_PER_STAGE)
*/
export function isEliteStage(stage: number): boolean {
return stage === 5;
export function isEliteSection(section: number): boolean {
return section === ELITE_SECTION;
}
/**
* 判断是否为 Boss 关
* @param stage 关卡号(1~10)
* 判断是否为 Boss 节(每关第 BOSS_SECTION 节,即末节)
* @param section 小节号(1~SECTIONS_PER_STAGE)
*/
export function isBossStage(stage: number): boolean {
return stage === 10;
export function isBossSection(section: number): boolean {
return section === BOSS_SECTION;
}
/**
* 获取小节类型
* @param stage 关卡号(1~10)
* 获取小节类型(按节号区分:1~3 普通 / 4 精英 / 5 Boss)
* @param section 小节号(1~SECTIONS_PER_STAGE)
*/
export function getSectionType(stage: number): SectionType {
if (isBossStage(stage)) return SectionType.Boss;
if (isEliteStage(stage)) return SectionType.Elite;
export function getSectionType(section: number): SectionType {
if (isBossSection(section)) return SectionType.Boss;
if (isEliteSection(section)) return SectionType.Elite;
return SectionType.Normal;
}
// ======================== 第 1 章配置 ========================
/** 生成单个大关的 10 个小节配置 */
/** 生成单个大关的 SECTIONS_PER_STAGE 个小节配置(1~3 普通 / 4 精英 / 5 Boss) */
function makeStageSections(stage: number): SectionConfig[] {
const type = getSectionType(stage);
const monLv = getMonsterLv(stage);
const sections: SectionConfig[] = [];
for (let i = 1; i <= 10; i++) {
for (let i = 1; i <= SECTIONS_PER_STAGE; i++) {
const type = getSectionType(i);
const section: SectionConfig = { type, monLv };
if (type === SectionType.Elite) {
@@ -164,7 +170,7 @@ function makeStageSections(stage: number): SectionConfig[] {
section.eliteCount = BOSS_ELITE_COUNT;
// bossUuid 缺省随机,由生成引擎从 Boss 池抽取
} else {
// 普通关:近战为主,穿插远程/重型
// 普通节:近战为主,穿插远程/重型
section.monTypes = [MonType.Melee, MonType.Melee, MonType.Melee, MonType.Heavy, MonType.Long];
}
@@ -200,7 +206,7 @@ export const ChapterSet: Record<number, ChapterConfig> = {
* 获取小节配置
* @param chapter 章节号
* @param stage 关卡号
* @param section 小节号(1~10)
* @param section 小节号(1~SECTIONS_PER_STAGE)
* @returns 小节配置,不存在时返回 null
*/
export function getSectionConfig(chapter: number, stage: number, section: number): SectionConfig | null {