feat: 接入通关弹窗
This commit is contained in:
111
assets/scripts/utils/AchievementTitleManager.ts
Normal file
111
assets/scripts/utils/AchievementTitleManager.ts
Normal file
@@ -0,0 +1,111 @@
|
||||
import { ACHIEVEMENT_TITLE_CONFIG, AchievementTitleConfigItem, INFINITE_ACHIEVEMENT_TITLE } from '../config/AchievementTitleConfig';
|
||||
|
||||
export interface AchievementTitleInfo {
|
||||
readonly titleText: string;
|
||||
readonly nextTitleText: string;
|
||||
readonly nextTitleProgress: number;
|
||||
readonly progressText: string;
|
||||
readonly completedLevelCount: number;
|
||||
readonly currentTitleStartCount: number;
|
||||
readonly nextTitleRequiredCount: number;
|
||||
readonly remainingToNextTitle: number;
|
||||
}
|
||||
|
||||
interface AchievementTitleStage {
|
||||
readonly titleText: string;
|
||||
readonly clearsToNext: number;
|
||||
readonly startCount: number;
|
||||
}
|
||||
|
||||
export class AchievementTitleManager {
|
||||
public static getTitleInfo(completedLevelCount: number): AchievementTitleInfo {
|
||||
const safeCompletedCount = AchievementTitleManager.normalizeCompletedCount(completedLevelCount);
|
||||
const stages = AchievementTitleManager.buildFiniteStages();
|
||||
const finiteResult = AchievementTitleManager.findFiniteStage(safeCompletedCount, stages);
|
||||
|
||||
if (finiteResult) {
|
||||
return AchievementTitleManager.createTitleInfo(safeCompletedCount, finiteResult.currentStage, finiteResult.nextStage);
|
||||
}
|
||||
|
||||
return AchievementTitleManager.createInfiniteTitleInfo(safeCompletedCount, stages[stages.length - 1]);
|
||||
}
|
||||
|
||||
private static normalizeCompletedCount(completedLevelCount: number): number {
|
||||
if (!Number.isFinite(completedLevelCount) || completedLevelCount < 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return Math.floor(completedLevelCount);
|
||||
}
|
||||
|
||||
private static buildFiniteStages(): AchievementTitleStage[] {
|
||||
let startCount = 0;
|
||||
|
||||
return ACHIEVEMENT_TITLE_CONFIG.map((item: AchievementTitleConfigItem) => {
|
||||
const stage: AchievementTitleStage = {
|
||||
titleText: item.levelName,
|
||||
clearsToNext: item.clearsToNext,
|
||||
startCount
|
||||
};
|
||||
startCount += item.clearsToNext;
|
||||
return stage;
|
||||
});
|
||||
}
|
||||
|
||||
private static findFiniteStage(completedLevelCount: number, stages: AchievementTitleStage[]): { currentStage: AchievementTitleStage; nextStage: AchievementTitleStage } | null {
|
||||
for (let index = 0; index < stages.length; index++) {
|
||||
const currentStage = stages[index];
|
||||
const nextStage = stages[index + 1] ?? {
|
||||
titleText: `${INFINITE_ACHIEVEMENT_TITLE.levelNamePrefix}1级`,
|
||||
clearsToNext: INFINITE_ACHIEVEMENT_TITLE.clearsToNext,
|
||||
startCount: currentStage.startCount + currentStage.clearsToNext
|
||||
};
|
||||
|
||||
if (completedLevelCount < nextStage.startCount) {
|
||||
return { currentStage, nextStage };
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private static createInfiniteTitleInfo(completedLevelCount: number, lastFiniteStage: AchievementTitleStage): AchievementTitleInfo {
|
||||
const infiniteStartCount = lastFiniteStage.startCount + lastFiniteStage.clearsToNext;
|
||||
const completedAfterInfiniteStart = Math.max(0, completedLevelCount - infiniteStartCount);
|
||||
const currentInfiniteLevel = Math.floor(completedAfterInfiniteStart / INFINITE_ACHIEVEMENT_TITLE.clearsToNext) + 1;
|
||||
const currentStageStartCount = infiniteStartCount + (currentInfiniteLevel - 1) * INFINITE_ACHIEVEMENT_TITLE.clearsToNext;
|
||||
const nextStage: AchievementTitleStage = {
|
||||
titleText: `${INFINITE_ACHIEVEMENT_TITLE.levelNamePrefix}${currentInfiniteLevel + 1}级`,
|
||||
clearsToNext: INFINITE_ACHIEVEMENT_TITLE.clearsToNext,
|
||||
startCount: currentStageStartCount + INFINITE_ACHIEVEMENT_TITLE.clearsToNext
|
||||
};
|
||||
|
||||
return AchievementTitleManager.createTitleInfo(
|
||||
completedLevelCount,
|
||||
{
|
||||
titleText: `${INFINITE_ACHIEVEMENT_TITLE.levelNamePrefix}${currentInfiniteLevel}级`,
|
||||
clearsToNext: INFINITE_ACHIEVEMENT_TITLE.clearsToNext,
|
||||
startCount: currentStageStartCount
|
||||
},
|
||||
nextStage
|
||||
);
|
||||
}
|
||||
|
||||
private static createTitleInfo(completedLevelCount: number, currentStage: AchievementTitleStage, nextStage: AchievementTitleStage): AchievementTitleInfo {
|
||||
const interval = Math.max(1, nextStage.startCount - currentStage.startCount);
|
||||
const completedInCurrentTitle = Math.max(0, completedLevelCount - currentStage.startCount);
|
||||
const remainingToNextTitle = Math.max(0, nextStage.startCount - completedLevelCount);
|
||||
const nextTitleProgress = Math.max(0, Math.min(1, completedInCurrentTitle / interval));
|
||||
|
||||
return {
|
||||
titleText: currentStage.titleText,
|
||||
nextTitleText: nextStage.titleText,
|
||||
nextTitleProgress,
|
||||
progressText: `还差${remainingToNextTitle}题获得${nextStage.titleText}`,
|
||||
completedLevelCount,
|
||||
currentTitleStartCount: currentStage.startCount,
|
||||
nextTitleRequiredCount: nextStage.startCount,
|
||||
remainingToNextTitle
|
||||
};
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user