refactor: 渲染端初始化移动至主插件

This commit is contained in:
unanmed 2026-10-16 00:41:58 +08:00
parent 7fde97ff1e
commit 0a133058ca
12 changed files with 118 additions and 187 deletions

View File

@ -35,19 +35,10 @@ import {
} from '@user/client-base';
import {
ExcitationDivider,
ExcitationVariator,
IExcitation,
IExcitationDivider,
RafExcitation
} from '@motajs/animate';
import {
DEBUG_DIVIDER,
DEBUG_VARIATOR,
DIVIDER_DEBUG_DIVIDER,
MAIN_HEIGHT,
MAIN_WIDTH,
VARIATOR_DEBUG_SPEED
} from './shared';
import { IRendererUsing, RendererUsing } from '@motajs/render-vue';
import { IUIController, UIController } from '@motajs/system';
import { createApp } from './render';
@ -71,7 +62,7 @@ export class ClientCore extends CoreState implements IClientCore {
readonly sceneController: IUIController<IGameUIPropsBase>;
readonly mainUIController: IUIController<IGameUIPropsBase>;
// Layer 5 渲染顶层
// Layer 5 渲染顶层 - 目前没东西
/** 已注册的渲染端插件 */
private readonly clientPlugins: Map<
@ -85,10 +76,7 @@ export class ClientCore extends CoreState implements IClientCore {
constructor(config: IClientCoreConfig) {
super(config);
//#region Layer 4
this.save = new SaveSystem();
this.save.init('');
this.audioContext = new MotaAudioContext();
this.soundPlayer = new SoundPlayer(this.audioContext);
this.bgmPlayer = new BGMPlayer(this.audioContext);
@ -98,30 +86,15 @@ export class ClientCore extends CoreState implements IClientCore {
config.tilesetUnit
);
const rafExcitation = new RafExcitation();
const excitationDivider = new ExcitationDivider<number>();
this.rafExcitation = rafExcitation;
this.excitationDivider = excitationDivider;
if (DEBUG_VARIATOR) {
const variator = new ExcitationVariator();
variator.bindExcitation(rafExcitation);
variator.setSpeed(VARIATOR_DEBUG_SPEED);
excitationDivider.bindExcitation(variator);
} else {
excitationDivider.bindExcitation(rafExcitation);
}
if (DEBUG_DIVIDER) {
excitationDivider.setDivider(DIVIDER_DEBUG_DIVIDER);
}
this.rafExcitation = new RafExcitation();
this.excitationDivider = new ExcitationDivider<number>();
this.renderer = new MotaRenderer({
canvas: '#render-main',
width: MAIN_WIDTH,
height: MAIN_HEIGHT,
width: config.renderWidth,
height: config.renderHeight,
// 使用分频器,用户可以在设置中调整,如果设备性能较差调高分频有助于提高性能表现
excitaion: excitationDivider
excitaion: this.excitationDivider
});
this.using = new RendererUsing(this.renderer);
this.mainMapRenderer = new MapRenderer(this.materials);
@ -133,8 +106,6 @@ export class ClientCore extends CoreState implements IClientCore {
this.sceneController.setPropsBaseCreator(pbCreator);
this.mainUIController.setPropsBaseCreator(pbCreator);
//#endregion
this.loader.addCoreConfig('client', config.clientURL);
// 渲染端插件注册表

View File

@ -2,25 +2,6 @@ import { ElementLocator, Font } from '@motajs/render';
// 本文件为 UI 配置文件,你可以修改下面的每个常量来控制 UI 的显示参数,每个常量都有注释说明
//#region 调试用参数
/**
* 渲染器的激励源是否使用变速器,使用后可以通过 {@link VARIATOR_DEBUG_SPEED} 调整激励源速度,
* 从而调整动画等内容的执行速度,方便调试
*/
export const DEBUG_VARIATOR = false;
/** 当使用变速器作为激励源调试时,变速器的速度 */
export const VARIATOR_DEBUG_SPEED = 0.2;
/**
* 是否使用分频器调试,使用后可以通过 {@link DIVIDER_DEBUG_DIVIDER} 调整分配比例,
* 降低画面刷新频率及每帧执行函数的执行频率,方便调试
*/
export const DEBUG_DIVIDER = false;
/** 当使用分频器调试时,分频比例 */
export const DIVIDER_DEBUG_DIVIDER = 60;
//#endregion
//#region 地图
/** 每个格子的默认宽度,现阶段用处不大 */

View File

@ -60,6 +60,10 @@ export interface IClientCoreConfig extends ICoreStateConfig {
readonly tilesetUnit: number;
/** 渲染器挂载至的画布元素 */
readonly rendererCanvas: string;
/** 渲染器的渲染宽度 */
readonly renderWidth: number;
/** 渲染器的渲染高度 */
readonly renderHeight: number;
/** 渲染端插件列表 */
readonly clientPlugins: IClientPluginDefine[];
}

View File

@ -78,7 +78,7 @@
"76": "Plugin dependency cycle detected: $1. Cyclic plugins will not be initialized.",
"77": "Plugin $1 depends on a non-existent plugin: $2. Related plugins will not be initialized.",
"78": "Duplicate plugin id: $1. The duplicate will not be registered.",
"79": "Hero attribute initialize failed since no core config loaded.",
"79": "$1 side initialize failed since no core config loaded.",
"2001": "Replay($1): Replay parameter count mismatch: expected $2, got $3.",
"2002": "Replay($1): Replay parameter type mismatch: index $2, expected $3, got $4.",
"2003": "Replay(move): Expected hero to be stopped before execute moving step.",

View File

@ -4,8 +4,17 @@ import {
IClientCore,
IClientCoreConfig
} from '@user/client-modules';
import { CLIENT_CORE_URL, TILESET_RESERVE, TILESET_UNIT } from '../constant';
import {
CLIENT_CORE_URL,
RENDER_CANVAS,
RENDER_HEIGHT,
RENDER_WIDTH,
TILESET_RESERVE,
TILESET_UNIT
} from '../constant';
import { createCoreStateConfig } from '../data/entry';
import { MainClientPlugin } from './initialize';
import { clientPlugins } from './plugin';
/**
* 创建渲染端配置对象
@ -18,6 +27,10 @@ export function createClientCoreConfig(
clientURL: CLIENT_CORE_URL,
tilesetReserve: TILESET_RESERVE,
tilesetUnit: TILESET_UNIT,
rendererCanvas: RENDER_CANVAS,
renderWidth: RENDER_WIDTH,
renderHeight: RENDER_HEIGHT,
clientPlugins: [new MainClientPlugin(), ...clientPlugins],
...createCoreStateConfig(starter)
};
@ -25,7 +38,7 @@ export function createClientCoreConfig(
}
/**
* 创建渲染端主对象,返回经过初始化的主对象实例
* 创建渲染端主对象,返回未经过异步初始化的主对象实例,需要手动调用 `state.load` 初始化
* @param starter 加载启动器
*/
export async function createClientCore(
@ -33,6 +46,5 @@ export async function createClientCore(
): Promise<IClientCore> {
const config = createClientCoreConfig(starter);
const state = new ClientCore(config);
await state.load();
return state;
}

54
src/client/initialize.ts Normal file
View File

@ -0,0 +1,54 @@
import { logger } from '@motajs/common';
import {
excitationDivider,
IClientCore,
IClientCoreConfig,
IClientPluginDefine
} from '@user/client-modules';
import { ICoreStateCoreConfig } from '@user/data-state';
import {
DEBUG_DIVIDER,
DEBUG_VARIATOR,
DIVIDER_DEBUG_DIVIDER,
VARIATOR_DEBUG_SPEED
} from '../constant';
import { ExcitationVariator } from '@motajs/animate';
export class MainClientPlugin implements IClientPluginDefine {
id: string = 'main-client-plugin';
dependencies: readonly string[] = [];
awake(state: IClientCore): void {
// 渲染调试配置
if (DEBUG_VARIATOR) {
const variator = new ExcitationVariator();
variator.bindExcitation(state.rafExcitation);
variator.setSpeed(VARIATOR_DEBUG_SPEED);
excitationDivider.bindExcitation(variator);
} else {
excitationDivider.bindExcitation(state.rafExcitation);
}
if (DEBUG_DIVIDER) {
excitationDivider.setDivider(DIVIDER_DEBUG_DIVIDER);
}
}
async initialize(): Promise<void> {}
async afterLoad(state: IClientCore): Promise<void> {
const core = state.loader.getConfig<ICoreStateCoreConfig>('core');
const client = state.loader.getConfig<IClientCoreConfig>('client');
if (!core) {
logger.error(79, 'Data');
return;
}
if (!client) {
logger.error(79, 'Client');
return;
}
// 存档初始化
state.save.init(`@game/${core.name}`);
}
}

View File

@ -0,0 +1 @@
export * from './list';

View File

@ -0,0 +1,4 @@
import { IClientPluginDefine } from '@user/client-modules';
/** 渲染端插件列表 */
export const clientPlugins: IClientPluginDefine[] = [];

View File

@ -13,6 +13,8 @@ export const HERO_FACE = FaceGroup.Dir8;
//#region 渲染端配置
/** 渲染端的渲染画布,不懂的话就不要动 */
export const RENDER_CANVAS = '#render-main';
/** 渲染端核心配置对象,不懂的话就不要动 */
export const CLIENT_CORE_URL = 'content/client.jsonc';
/** Tileset 预留数量,用于控制最大允许注册多少个普通图块,例如填写 10000 表示最大 10000 个普通图块,不懂的话不要动 */
@ -20,4 +22,30 @@ export const TILESET_RESERVE = 100000;
/** 一个 Tileset 的图块数量单位,例如 10000 时表示一个 Tileset 会占用 10000 或 10000 的倍数个图块,不懂的话不要动 */
export const TILESET_UNIT = 10000;
// 关于渲染的其他配置可在 ./client/ui/config.ts 中修改,
// 关于高级渲染设置,请参考样板使用文档,那里会进行更详细的讲解。
/** 渲染器的渲染宽度,默认为地图宽度 416 + 左侧状态栏宽度 180 */
export const RENDER_WIDTH = 416 + 180;
/** 渲染器的渲染高度,默认为地图高度 416 */
export const RENDER_HEIGHT = 416;
//#endregion
//#region 渲染端调试配置
/**
* 渲染器的激励源是否使用变速器,使用后可以通过 {@link VARIATOR_DEBUG_SPEED} 调整激励源速度,
* 从而调整动画等内容的执行速度,方便调试
*/
export const DEBUG_VARIATOR = false;
/** 当使用变速器作为激励源调试时,变速器的速度 */
export const VARIATOR_DEBUG_SPEED = 0.2;
/**
* 是否使用分频器调试,使用后可以通过 {@link DIVIDER_DEBUG_DIVIDER} 调整分配比例,
* 降低画面刷新频率及每帧执行函数的执行频率,方便调试
*/
export const DEBUG_DIVIDER = false;
/** 当使用分频器调试时,分频比例 */
export const DIVIDER_DEBUG_DIVIDER = 60;
//#endregion

View File

@ -22,7 +22,7 @@ export function createCoreStateConfig(
}
/**
* 创建数据端主对象,返回未经过初始化的主对象实例,需要手动调用 `state.load` 初始化
* 创建数据端主对象,返回未经过异步初始化的主对象实例,需要手动调用 `state.load` 初始化
* @param starter 加载启动器
*/
export function createCoreState(starter: ILoadTaskStarter): ICoreState {

View File

@ -63,7 +63,7 @@ export class MainDataPlugin implements IDataPluginDefine {
// 进行勇士的加载后初始化
const coreConfig = state.loader.getConfig<ICoreStateCoreConfig>('core');
if (!coreConfig) {
logger.error(79);
logger.error(79, 'Data');
return;
}
const dir = state.faceManager.get(this.heroFace);

View File

@ -1,131 +1,7 @@
// 部分全局css特效
#root {
position: fixed;
display: block;
width: 0;
height: 0;
z-index: 1000;
overflow: visible;
font-size: 16px;
user-select: none;
}
.antdv-message {
font-family: 'normal';
font-size: 1.6em;
}
// 文字按钮
.button-text {
cursor: pointer;
transition: color 0.2s linear;
}
.button-text[active='true'],
.button-text:hover {
color: aqua;
}
.button-text:active {
color: aquamarine;
}
.button-text[danger='true'][danger-display='true'] {
color: rgb(255, 47, 47);
}
.button-text[danger='true']:hover,
.button-text[danger='true'][active='true'] {
color: rgb(255, 120, 120);
}
.button-text[danger='true']:active {
color: rgb(255, 182, 182);
}
.selectable {
border: #0000 0.5px solid;
padding: 1% 3% 1% 3%;
#game-draw {
width: 100%;
}
.selectable[selected='true'] {
animation: selected alternate 5s infinite ease-in-out;
}
@keyframes selected {
0% {
border: #0ff7 0.5px solid;
background-color: rgba(39, 251, 209, 0.143);
}
50% {
border: #0ffa 0.5px solid;
background-color: rgba(39, 251, 209, 0.284);
}
100% {
border: #0ff7 0.5px solid;
background-color: rgba(39, 251, 209, 0.143);
}
}
// 拖拽类
.draginable {
transition: background-color 0.2s linear;
}
.draginable[draged='true'][access='true']:hover {
background-color: rgba(0, 255, 187, 0.31);
}
.draginable[draged='true'][access='false']:hover {
background-color: rgba(255, 0, 0, 0.319);
cursor: not-allowed;
}
#non-ui {
position: absolute;
z-index: 999;
user-select: none;
}
.changable {
border-radius: 4px;
padding: 2px 4px;
}
.changable[change='true'] {
animation: changable-animate 1s linear alternate 1;
}
@keyframes changable-animate {
0% {
background-color: #7cc9;
}
100% {
background-color: #0000;
}
}
div.toolbar-editor-item {
display: flex;
flex-direction: row;
justify-content: space-between;
align-items: center;
width: 100%;
}
.danmaku {
margin-left: 10px;
height: 100%;
display: flex;
justify-content: center;
align-items: center;
}
.motajs-input-element {
left: 0;
top: 0;
position: fixed;
border: none;
z-index: 1000;
background-color: transparent;
}