From f8c9a2349cd78634bbf81be1e2764b3d81765214 Mon Sep 17 00:00:00 2001 From: unanmed <1319491857@qq.com> Date: Tue, 25 Nov 2025 12:48:55 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E5=8B=87=E5=A3=AB=E8=B7=9F=E9=9A=8F?= =?UTF-8?q?=E8=80=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/render/components/textbox.tsx | 2 + .../src/render/map/extension/hero.ts | 2 +- .../client-modules/src/render/map/moving.ts | 4 +- .../client-modules/src/render/map/renderer.ts | 43 ++++++++++++++++- .../client-modules/src/render/map/types.ts | 46 +++++++++++++++++++ .../client-modules/src/render/map/vertex.ts | 37 +++++++++------ .../legacy-plugin-data/src/fallback.ts | 26 +++++++---- public/libs/events.js | 25 +--------- 8 files changed, 136 insertions(+), 49 deletions(-) diff --git a/packages-user/client-modules/src/render/components/textbox.tsx b/packages-user/client-modules/src/render/components/textbox.tsx index 18703f0..5b327ad 100644 --- a/packages-user/client-modules/src/render/components/textbox.tsx +++ b/packages-user/client-modules/src/render/components/textbox.tsx @@ -33,6 +33,8 @@ import { import { SetupComponentOptions } from '@motajs/system-ui'; import { texture } from '../elements'; +// todo: TextContent 应该改成渲染元素? + //#region TextContent export interface TextContentProps diff --git a/packages-user/client-modules/src/render/map/extension/hero.ts b/packages-user/client-modules/src/render/map/extension/hero.ts index efbe92d..79df2cd 100644 --- a/packages-user/client-modules/src/render/map/extension/hero.ts +++ b/packages-user/client-modules/src/render/map/extension/hero.ts @@ -283,7 +283,6 @@ export class MapHeroRenderer implements IMapHeroRenderer { this.heroEntity.moving = true; this.heroEntity.animating = true; this.heroEntity.lastAnimateTime = this.ticker.timestamp; - this.heroEntity.block.useSpecifiedFrame(1); } private endEntityMoving(entity: HeroRenderEntity) { @@ -381,6 +380,7 @@ export class MapHeroRenderer implements IMapHeroRenderer { promise: Promise.resolve(), animateDirection: HeroAnimateDirection.Forward }; + moving.useSpecifiedFrame(0); this.entities.push(entity); } diff --git a/packages-user/client-modules/src/render/map/moving.ts b/packages-user/client-modules/src/render/map/moving.ts index 89b5635..5c449f0 100644 --- a/packages-user/client-modules/src/render/map/moving.ts +++ b/packages-user/client-modules/src/render/map/moving.ts @@ -201,7 +201,7 @@ export class MovingBlock extends DynamicBlockStatus implements IMovingBlock { this.y = this.targetY; this.end = true; this.promiseFunc(); - return false; + return true; } else { const timeProgress = dt / this.time; const progress = this.timing(timeProgress); @@ -220,7 +220,7 @@ export class MovingBlock extends DynamicBlockStatus implements IMovingBlock { } this.end = true; this.promiseFunc(); - return false; + return true; } else { const timeProgress = dt / this.time; const progress = this.timing(timeProgress); diff --git a/packages-user/client-modules/src/render/map/renderer.ts b/packages-user/client-modules/src/render/map/renderer.ts index 4a37dd7..f37e8f4 100644 --- a/packages-user/client-modules/src/render/map/renderer.ts +++ b/packages-user/client-modules/src/render/map/renderer.ts @@ -18,6 +18,7 @@ import { IMapBackgroundConfig, IMapRenderConfig, IMapRenderer, + IMapRendererPostEffect, IMapRendererTicker, IMapVertexGenerator, IMapViewportController, @@ -172,6 +173,11 @@ export class MapRenderer /** 画布上下文数据 */ private contextData: IContextData; + /** 效果对象优先级映射 */ + private effectPriority: Map = new Map(); + /** 渲染器效果对象列表,使用数组是因为要有顺序 */ + private postEffects: IMapRendererPostEffect[] = []; + /** 地图变换矩阵 */ transform: Transform; /** 是否需要更新变换矩阵 */ @@ -293,6 +299,40 @@ export class MapRenderer gl.bindVertexArray(null); } + private sortPostEffect() { + this.postEffects.sort((a, b) => { + const pa = this.effectPriority.get(a) ?? 0; + const pb = this.effectPriority.get(b) ?? 0; + return pb - pa; + }); + } + + addPostEffect(effect: IMapRendererPostEffect, priority: number): void { + this.postEffects.push(effect); + this.effectPriority.set(effect, priority); + this.sortPostEffect(); + this.updateRequired = true; + } + + removePostEffect(effect: IMapRendererPostEffect): void { + const index = this.postEffects.indexOf(effect); + if (index === -1) return; + this.postEffects.splice(index); + this.effectPriority.delete(effect); + this.sortPostEffect(); + this.updateRequired = true; + } + + setPostEffectPriority( + effect: IMapRendererPostEffect, + priority: number + ): void { + if (!this.effectPriority.has(effect)) return; + this.effectPriority.set(effect, priority); + this.sortPostEffect(); + this.updateRequired = true; + } + //#endregion //#region 状态控制 @@ -646,7 +686,7 @@ export class MapRenderer gl.disable(gl.CULL_FACE); gl.enable(gl.DEPTH_TEST); gl.enable(gl.BLEND); - gl.depthFunc(gl.LEQUAL); + gl.depthFunc(gl.LESS); gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA); const data: IContextData = { @@ -1209,6 +1249,7 @@ export class MapRenderer } render(): HTMLCanvasElement { + // todo: 改为 FBO,最后把 FBO 画到画布上 const gl = this.gl; const data = this.contextData; if (!this.assetData) { diff --git a/packages-user/client-modules/src/render/map/types.ts b/packages-user/client-modules/src/render/map/types.ts index 77ad5e2..74cd28b 100644 --- a/packages-user/client-modules/src/render/map/types.ts +++ b/packages-user/client-modules/src/render/map/types.ts @@ -266,6 +266,29 @@ export interface IMapRendererTicker { remove(): void; } +export interface IMapRendererPostEffect { + /** + * 初始化渲染器效果对象,一般是编译着色器、准备数据缓冲区等 + * @param gl WebGL2 画布上下文 + * @param data 地图渲染的上下文数据 + */ + init(gl: WebGL2RenderingContext, data: IContextData): void; + + /** + * 渲染效果对象,将内容渲染到输出 FBO 上 + * @param gl WebGL2 画布上下文 + * @param data 地图渲染的上下文数据 + * @param input 输入 FBO + * @param output 输出 FBO,内容要画到这个 FBO 上 + */ + render( + gl: WebGL2RenderingContext, + data: IContextData, + input: WebGLFramebuffer, + output: WebGLFramebuffer + ): void; +} + export interface IMapRenderer { /** 地图渲染器使用的资源管理器 */ readonly manager: IMaterialManager; @@ -313,6 +336,29 @@ export interface IMapRenderer { */ destroy(): void; + /** + * 添加一个地图渲染器效果对象,一般是对地图渲染的后处理,可以是一些特效和自定义绘制等 + * @param effect 地图渲染器效果对象 + * @param priority 效果对象优先级 + */ + addPostEffect(effect: IMapRendererPostEffect, priority: number): void; + + /** + * 移除指定的效果对象 + * @param effect 地图渲染器效果对象 + */ + removePostEffect(effect: IMapRendererPostEffect): void; + + /** + * 设置效果对象的优先级 + * @param effect 地图渲染器效果对象 + * @param priority 效果对象优先级 + */ + setPostEffectPriority( + effect: IMapRendererPostEffect, + priority: number + ): void; + /** * 渲染地图 */ diff --git a/packages-user/client-modules/src/render/map/vertex.ts b/packages-user/client-modules/src/render/map/vertex.ts index 86b0b60..b62863d 100644 --- a/packages-user/client-modules/src/render/map/vertex.ts +++ b/packages-user/client-modules/src/render/map/vertex.ts @@ -365,7 +365,8 @@ export class MapVertexGenerator assetIndex: number, offsetIndex: number, frames: number, - update: VertexUpdate + update: VertexUpdate, + dynamic: boolean ) { const { instancedArray } = vertex; // 顶点数组 @@ -377,8 +378,9 @@ export class MapVertexGenerator const layerIndex = this.renderer.getLayerIndex(index.layer); // 避免 z 坐标是 1 的时候被裁剪,因此范围选择 [-0.9, 0.9] const layerStart = (layerIndex / layerCount) * 1.8 - 0.9; - const zIndex = - -layerStart - index.mapY / this.mapHeight / layerCount; + const perBlockZ = 1 / this.mapHeight / layerCount; + const blockZ = index.mapY * perBlockZ; + const zIndex = -layerStart - blockZ - (dynamic ? perBlockZ : 0); const { x, y, w, h } = this.getTilePosition(index, width, height); // 图块位置 instancedArray[startIndex] = x; @@ -418,7 +420,8 @@ export class MapVertexGenerator vertex: IMapVertexData, index: BlockIndex, tile: IMaterialFramedData, - update: VertexUpdate + update: VertexUpdate, + dynamic: boolean ) { const autotile = this.renderer.autotile; const { connection, center } = autotile.connect( @@ -442,7 +445,8 @@ export class MapVertexGenerator assetIndex, offsetIndex, tile.frames, - update + update, + dynamic ); } @@ -485,7 +489,8 @@ export class MapVertexGenerator vertex, newIndex, tile, - VertexUpdate.Texture + VertexUpdate.Texture, + false ); block.data.markRenderDirty(); } @@ -501,7 +506,8 @@ export class MapVertexGenerator mapArray: Uint32Array, vertex: IMapVertexData, index: BlockIndex, - num: number + num: number, + dynamic: boolean ) { // 此处仅更新当前图块,不更新周围一圈的自动元件 // 周围一圈的自动元件需要在更新某个图块或者某个区域时处理,不在这里处理 @@ -526,7 +532,8 @@ export class MapVertexGenerator vertex, index, tile, - VertexUpdate.All + VertexUpdate.All, + dynamic ); } else { // 正常图块 @@ -553,7 +560,8 @@ export class MapVertexGenerator assetIndex, offsetIndex, tile.frames, - VertexUpdate.All + VertexUpdate.All, + dynamic ); } } @@ -600,7 +608,7 @@ export class MapVertexGenerator this.checkAutotileConnectionAround(layer, array, index, -1, 1); this.checkAutotileConnectionAround(layer, array, index, -1, 0); // 再更新当前图块 - this.updateVertexArray(array, vertex, index, num); + this.updateVertexArray(array, vertex, index, num, false); block.data.markRenderDirty(); } @@ -795,7 +803,8 @@ export class MapVertexGenerator array, vertex, index, - array[mapIndex] + array[mapIndex], + false ); } } @@ -840,7 +849,8 @@ export class MapVertexGenerator assetIndex, offset, frames, - update + update, + true ); } else { // 正常图块 @@ -859,7 +869,8 @@ export class MapVertexGenerator assetIndex, offset, frames, - update + update, + true ); } diff --git a/packages-user/legacy-plugin-data/src/fallback.ts b/packages-user/legacy-plugin-data/src/fallback.ts index 2ac4712..f1f6cef 100644 --- a/packages-user/legacy-plugin-data/src/fallback.ts +++ b/packages-user/legacy-plugin-data/src/fallback.ts @@ -171,7 +171,11 @@ export function initFallback() { patch.add( 'setHeroLoc', - function (name: 'x' | 'y' | 'direction', value: number | Dir) { + function ( + name: 'x' | 'y' | 'direction', + value: number | Dir, + noGather?: boolean + ) { if (!core.status.hero) return; // @ts-ignore core.status.hero.loc[name] = value; @@ -182,17 +186,21 @@ export function initFallback() { } else if (name === 'x') { // 为了防止逆天样板出问题 core.bigmap.posX = value as number; - state.hero.setPosition( - value as number, - core.status.hero.loc.y - ); + if (!noGather) { + state.hero.setPosition( + value as number, + core.status.hero.loc.y + ); + } } else { // 为了防止逆天样板出问题 core.bigmap.posY = value as number; - state.hero.setPosition( - core.status.hero.loc.x, - value as number - ); + if (!noGather) { + state.hero.setPosition( + core.status.hero.loc.x, + value as number + ); + } } } ); diff --git a/public/libs/events.js b/public/libs/events.js index a4d3827..3121369 100644 --- a/public/libs/events.js +++ b/public/libs/events.js @@ -3489,33 +3489,12 @@ events.prototype.hasAsyncAnimate = function () { ////// 跟随 ////// events.prototype.follow = function (name) { - name = core.getMappedName(name); - if (core.material.images.images[name]) { - core.status.hero.followers.push({ name: name }); - core.gatherFollowers(); - core.clearMap('hero'); - core.drawHero(); - } - core.clearRouteFolding(); + // Deprecated. Use state.hero.addFollower instead. }; ////// 取消跟随 ////// events.prototype.unfollow = function (name) { - if (!name) { - core.status.hero.followers = []; - } else { - name = core.getMappedName(name); - for (var i = 0; i < core.status.hero.followers.length; i++) { - if (core.status.hero.followers[i].name == name) { - core.status.hero.followers.splice(i, 1); - break; - } - } - } - core.gatherFollowers(); - core.clearMap('hero'); - core.drawHero(); - core.clearRouteFolding(); + // Deprecated. Use state.hero.removeFollower instead. }; events.prototype._updateValueByOperator = function (