Files
KateLegend2_proj/assets/scripts/GameBoot.ts
T
2026-05-06 08:17:32 +08:00

92 lines
3.5 KiB
TypeScript

import { _decorator, Component, director, screen, view, Settings, settings, sys, game, view as viewMgr } from 'cc';
import { DESIGN_WIDTH, DESIGN_HEIGHT, TARGET_FPS } from './common/Constants';
import { UIFlowMgr, ISceneEnter } from './ui/UIFlowMgr';
const { ccclass } = _decorator;
/**
* Game bootstrap component. Attached to the root node of the initial scene
* (`assets/scenes/Boot.scene`). Responsible for:
*
* 1. Locking landscape orientation (requirement - tech-stack constraint).
* 2. Forcing the design resolution to 960x540 with the "fit height" policy
* so that any wider aspect ratio (18:9 / 19.5:9 / 20:9) simply extends
* horizontally without distorting the UI (requirement 1.7 / 18.6).
* 3. Locking frame rate to 30 fps (requirement 18.1-18.3).
* 4. Loading the first gameplay-facing scene (story intro if not seen, else
* main menu). This is the very first place we branch on the local storage
* flag defined in `STORAGE_KEY.StoryIntroSeen` (requirement 19.5).
*
* NOTE: Do NOT put any heavy logic here; this component runs on the very
* first frame and must stay cheap.
*/
@ccclass('GameBoot')
export class GameBoot extends Component {
protected onLoad(): void {
this.lockOrientationLandscape();
this.applyDesignResolution();
this.lockFrameRate();
}
protected start(): void {
// Drive the very first scene transition through UIFlowMgr so that
// story-intro / main-menu selection lives in one place (req 19.5).
const flow = new UIFlowMgr(undefined, {
onSceneEnter: (ev: ISceneEnter) => this.jumpToScene(ev),
});
flow.onBoot();
}
/**
* Translate the abstract UIFlow event into a concrete Cocos scene load.
* Boot scene itself never needs persisting; once we jump away the node
* is discarded naturally.
*/
private jumpToScene(ev: ISceneEnter): void {
const map: Record<string, string> = {
story_intro: 'StoryIntro',
main_menu: 'MainMenu',
};
const scene = map[ev.scene];
if (scene) {
director.loadScene(scene);
}
}
/**
* Lock the device to landscape. On WeChat Mini Game this is declared in
* `game.json` (deviceOrientation: "landscape"); on web/simulator we call
* the `screen.orientation` API when available.
*/
private lockOrientationLandscape(): void {
// `screen.orientation` is not declared as writable in every engine
// build, so we access it guardedly.
try {
// @ts-ignore - engine API surface differs across platforms.
if (typeof screen.orientation === 'number') {
// macro.ORIENTATION_LANDSCAPE = 3 in Cocos Creator 3.8.
// @ts-ignore - write is legal on runtime builds.
screen.orientation = 3;
}
} catch (e) {
// Silently ignore: editor preview already enforces orientation
// through `profiles/v2/project.json`.
}
}
/**
* Apply the 960x540 landscape design resolution. Any physical screen
* whose aspect ratio is >= 16:9 will simply show more horizontal world;
* narrower screens (unlikely on landscape) will letterbox.
*/
private applyDesignResolution(): void {
const v = view;
v.setDesignResolutionSize(DESIGN_WIDTH, DESIGN_HEIGHT, 4 /* FIT_HEIGHT */);
}
/** Clamp the engine game loop to 30 fps. */
private lockFrameRate(): void {
game.frameRate = TARGET_FPS;
}
}