diff --git a/packages-user/client-base/src/material/builder.ts b/packages-user/client-base/src/material/builder.ts index 4d1307a..1b3f73b 100644 --- a/packages-user/client-base/src/material/builder.ts +++ b/packages-user/client-base/src/material/builder.ts @@ -125,12 +125,13 @@ class TrackedAssetData } const origin = this.originSourceMap.get(index); const prev = this.sourceList.get(index); - if (origin) { + if (origin && origin !== source) { this.skipRef.delete(origin); } if (prev) { this.skipRef.delete(prev); } + this.originSourceMap.set(index, source); if (source instanceof ImageBitmap) { if (this.skipRef.has(source)) return; this.sourceList.set(index, source); @@ -141,7 +142,6 @@ class TrackedAssetData this.skipRef.set(bitmap, index); // 要把源也加到映射中,因为这里的 bitmap 与外部源并不同引用 this.skipRef.set(source, index); - this.originSourceMap.set(index, source); } this.dirty(index); } diff --git a/packages-user/client-modules/src/render/commonIns.ts b/packages-user/client-modules/src/render/commonIns.ts index def22fb..79395d2 100644 --- a/packages-user/client-modules/src/render/commonIns.ts +++ b/packages-user/client-modules/src/render/commonIns.ts @@ -5,4 +5,4 @@ import { materials } from '@user/client-base'; /** 主地图渲染器,用于渲染游戏画面 */ export const mainMapRenderer = new MapRenderer(materials, state.layer); /** 副地图渲染器,用于渲染缩略图、浏览地图等 */ -export const expandMapRenderer = new MapRenderer(materials, state.layer); +// export const expandMapRenderer = new MapRenderer(materials, state.layer); diff --git a/packages-user/client-modules/src/render/map/block.ts b/packages-user/client-modules/src/render/map/block.ts index 2d3520e..ab8800e 100644 --- a/packages-user/client-modules/src/render/map/block.ts +++ b/packages-user/client-modules/src/render/map/block.ts @@ -158,7 +158,7 @@ export class BlockSplitter implements IBlockSplitter { const bx = Math.floor(x / this.blockWidth); const by = Math.floor(y / this.blockHeight); if (!this.checkLocRange(bx, by)) return null; - const index = y * this.width + x; + const index = by * this.width + bx; return this.blockMap.get(index) ?? null; } diff --git a/packages-user/client-modules/src/render/map/renderer.ts b/packages-user/client-modules/src/render/map/renderer.ts index 443c90a..14cd6e7 100644 --- a/packages-user/client-modules/src/render/map/renderer.ts +++ b/packages-user/client-modules/src/render/map/renderer.ts @@ -1230,8 +1230,12 @@ export class MapRenderer const area = this.viewport.getRenderArea(); area.blockList.forEach(v => { - this.vertex.updateBlockCache(v); - v.data.render(); + if (v.data.dirty) { + this.vertex.updateBlockCache(v); + } + if (v.data.renderDirty) { + v.data.render(); + } }); if (area.dirty.length > 0) { diff --git a/packages-user/client-modules/src/render/map/vertex.ts b/packages-user/client-modules/src/render/map/vertex.ts index c1e60f0..f437369 100644 --- a/packages-user/client-modules/src/render/map/vertex.ts +++ b/packages-user/client-modules/src/render/map/vertex.ts @@ -470,17 +470,19 @@ export class MapVertexGenerator if (!block) return; const vertex = block.data.getLayerData(layer); if (!vertex) return; + const bx = mx - block.dataX; + const by = my - block.dataY; const newIndex: BlockIndex = { layer, mapX: mx, mapY: my, mapIndex: my * this.mapWidth + mx, - blockX: block.x, - blockY: block.y, - blockIndex: block.y * block.width + block.x + blockX: bx, + blockY: by, + blockIndex: by * block.width + bx }; - const tile = this.renderer.manager.getTile(mapArray[index.mapIndex]); - if (!tile) return; + const tile = this.renderer.manager.getTile(mapArray[newIndex.mapIndex]); + if (!tile || tile.cls !== BlockCls.Autotile) return; this.updateAutotile( mapArray, vertex, @@ -590,6 +592,7 @@ export class MapVertexGenerator blockY: block.y, blockIndex: dIndex }; + // 需要检查周围一圈的自动元件 this.checkAutotileConnectionAround(layer, array, index, -1, -1); this.checkAutotileConnectionAround(layer, array, index, 0, -1); @@ -669,98 +672,100 @@ export class MapVertexGenerator this.checkUpdateCallPerformance('updateBlockList'); } this.checkRebuild(); - if (blocks.length > 50) { - // 对于超出50个的更新操作使用懒更新 - blocks.forEach(v => { - const block = this.block.getBlockByDataLoc(v.x, v.y); - if (!block) return; - const bx = v.x - block.dataX; - const by = v.y - block.dataY; - block.data.markDirty(layer, bx - 1, by - 1, bx + 2, by + 2); - block.data.markRenderDirty(); - const left = bx === 0; - const top = by === 0; - const right = bx === block.width - 1; - const bottom = by === block.height - 1; - // 需要更一圈的自动元件 - if (left) { - // 左侧的分块需要更新 - const nextBlock = block.left(); - if (nextBlock) { - const { width: w, data } = nextBlock; - data.markDirty(layer, w - 1, by - 1, w, by + 1); - data.markRenderDirty(); - } - if (top) { - // 左上侧的分块需要更新 - const nextBlock = block.leftUp(); - if (nextBlock) { - const { width: w, height: h, data } = nextBlock; - data.markDirty(layer, w - 1, h - 1, w, h); - data.markRenderDirty(); - } - } - if (bottom) { - // 左下侧的分块需要更新 - const nextBlock = block.leftDown(); - if (nextBlock) { - const { width: w, data } = nextBlock; - data.markDirty(layer, w - 1, 0, w, 1); - data.markRenderDirty(); - } - } - } - if (top) { - // 上侧的分块需要更新 - const nextBlock = block.up(); - if (nextBlock) { - const { height: h, data } = nextBlock; - data.markDirty(layer, bx - 1, h - 1, bx + 1, h); - data.markRenderDirty(); - } - } - if (right) { - // 右侧的分块需要更新 - const nextBlock = block.right(); - if (nextBlock) { - const { data } = nextBlock; - data.markDirty(layer, 0, by - 1, 1, by + 1); - data.markRenderDirty(); - } - if (top) { - // 右上侧的分块需要更新 - const nextBlock = block.rightUp(); - if (nextBlock) { - const { height: h, data } = nextBlock; - data.markDirty(layer, 0, h - 1, 1, h); - data.markRenderDirty(); - } - } - if (bottom) { - // 右下侧的分块需要更新 - const nextBlock = block.rightDown(); - if (nextBlock) { - const { data } = nextBlock; - data.markDirty(layer, 0, 0, 1, 1); - data.markRenderDirty(); - } - } - } - if (bottom) { - // 下侧的分块需要更新 - const nextBlock = block.down(); - if (nextBlock) { - const { data } = nextBlock; - data.markDirty(layer, bx - 1, 0, bx + 1, 1); - data.markRenderDirty(); - } - } - }); - } else { + + if (blocks.length <= 50) { blocks.forEach(({ block: num, x, y }) => { this.updateBlockVertex(layer, num, x, y); }); + return; } + + // 对于超出50个的更新操作使用懒更新 + blocks.forEach(v => { + const block = this.block.getBlockByDataLoc(v.x, v.y); + if (!block) return; + const bx = v.x - block.dataX; + const by = v.y - block.dataY; + block.data.markDirty(layer, bx - 1, by - 1, bx + 2, by + 2); + block.data.markRenderDirty(); + const left = bx === 0; + const top = by === 0; + const right = bx === block.width - 1; + const bottom = by === block.height - 1; + // 需要更一圈的自动元件 + if (left) { + // 左侧的分块需要更新 + const nextBlock = block.left(); + if (nextBlock) { + const { width: w, data } = nextBlock; + data.markDirty(layer, w - 1, by - 1, w, by + 1); + data.markRenderDirty(); + } + if (top) { + // 左上侧的分块需要更新 + const nextBlock = block.leftUp(); + if (nextBlock) { + const { width: w, height: h, data } = nextBlock; + data.markDirty(layer, w - 1, h - 1, w, h); + data.markRenderDirty(); + } + } + if (bottom) { + // 左下侧的分块需要更新 + const nextBlock = block.leftDown(); + if (nextBlock) { + const { width: w, data } = nextBlock; + data.markDirty(layer, w - 1, 0, w, 1); + data.markRenderDirty(); + } + } + } + if (top) { + // 上侧的分块需要更新 + const nextBlock = block.up(); + if (nextBlock) { + const { height: h, data } = nextBlock; + data.markDirty(layer, bx - 1, h - 1, bx + 1, h); + data.markRenderDirty(); + } + } + if (right) { + // 右侧的分块需要更新 + const nextBlock = block.right(); + if (nextBlock) { + const { data } = nextBlock; + data.markDirty(layer, 0, by - 1, 1, by + 1); + data.markRenderDirty(); + } + if (top) { + // 右上侧的分块需要更新 + const nextBlock = block.rightUp(); + if (nextBlock) { + const { height: h, data } = nextBlock; + data.markDirty(layer, 0, h - 1, 1, h); + data.markRenderDirty(); + } + } + if (bottom) { + // 右下侧的分块需要更新 + const nextBlock = block.rightDown(); + if (nextBlock) { + const { data } = nextBlock; + data.markDirty(layer, 0, 0, 1, 1); + data.markRenderDirty(); + } + } + } + if (bottom) { + // 下侧的分块需要更新 + const nextBlock = block.down(); + if (nextBlock) { + const { data } = nextBlock; + data.markDirty(layer, bx - 1, 0, bx + 1, 1); + data.markRenderDirty(); + } + } + }); } updateBlockCache(block: Readonly>): void { @@ -1036,6 +1041,9 @@ class MapVertexBlock implements IMapVertexBlock { this.dirty = false; } + /** + * 标记为需要更新渲染缓冲区 + */ markRenderDirty() { this.renderDirty = true; } diff --git a/packages-user/client-modules/src/render/map/viewport.ts b/packages-user/client-modules/src/render/map/viewport.ts index 9de51ef..e5d7012 100644 --- a/packages-user/client-modules/src/render/map/viewport.ts +++ b/packages-user/client-modules/src/render/map/viewport.ts @@ -128,7 +128,7 @@ export class MapViewport implements IMapViewportController { return { render: renderArea, dirty: updateArea, - blockList: blockList.filter(v => v.data.dirty) + blockList: blockList }; } diff --git a/packages-user/data-state/src/core.ts b/packages-user/data-state/src/core.ts index 283f184..34f1f8d 100644 --- a/packages-user/data-state/src/core.ts +++ b/packages-user/data-state/src/core.ts @@ -26,7 +26,7 @@ export class CoreState implements ICoreState { loadState(data: IStateSaveData): void { this.hero.removeAllFollowers(); - data.followers.forEach(v => { + data?.followers.forEach(v => { this.hero.addFollower(v.num, v.identifier); }); } diff --git a/packages-user/data-state/src/map/mapLayer.ts b/packages-user/data-state/src/map/mapLayer.ts index d17073e..82607fa 100644 --- a/packages-user/data-state/src/map/mapLayer.ts +++ b/packages-user/data-state/src/map/mapLayer.ts @@ -7,6 +7,8 @@ import { } from './types'; import { Hookable, HookController, logger } from '@motajs/common'; +// todo: 提供 core.setBlock 等方法的替代方法,同时添加 setBlockList,以及前景背景的接口 + export class MapLayer extends Hookable implements IMapLayer diff --git a/packages/render-assets/src/streamComposer.ts b/packages/render-assets/src/streamComposer.ts index d8f6e7a..cf01f34 100644 --- a/packages/render-assets/src/streamComposer.ts +++ b/packages/render-assets/src/streamComposer.ts @@ -140,6 +140,7 @@ export class TextureMaxRectsStreamComposer private nextCanvas() { this.nowCanvas = document.createElement('canvas'); + this.nowCanvas.id = `${Math.random()}`; this.nowCtx = this.nowCanvas.getContext('2d')!; this.nowCanvas.width = this.maxWidth; this.nowCanvas.height = this.maxHeight; diff --git a/public/libs/maps.js b/public/libs/maps.js index 9006e0b..25c957a 100644 --- a/public/libs/maps.js +++ b/public/libs/maps.js @@ -3138,6 +3138,11 @@ maps.prototype.showBlock = function (x, y, floorId) { block?.id ?? 0, 0 ); + if (floorId === core.status.floorId) { + const { layer } = Mota.require('@user/data-state').state; + const event = layer.getLayerByAlias('event'); + event.setBlock(block.id, x, y); + } // 在本层,添加动画 if (floorId == core.status.floorId) { if (block.event.cls == 'autotile') { @@ -3170,6 +3175,11 @@ maps.prototype.hideBlock = function (x, y, floorId) { 0, block?.id ?? 0 ); + if (floorId === core.status.floorId) { + const { layer } = Mota.require('@user/data-state').state; + const event = layer.getLayerByAlias('event'); + event.setBlock(0, x, y); + } // 删除动画,清除地图 this._removeBlockFromMap(floorId, block); @@ -3193,6 +3203,11 @@ maps.prototype.hideBlockByIndex = function (index, floorId) { 0, block?.id ?? 0 ); + if (floorId === core.status.floorId) { + const { layer } = Mota.require('@user/data-state').state; + const event = layer.getLayerByAlias('event'); + event.setBlock(0, x, y); + } }; ////// 一次性隐藏多个block ////// @@ -3265,6 +3280,11 @@ maps.prototype.removeBlockByIndex = function (index, floorId) { 0, block?.id ?? 0 ); + if (floorId === core.status.floorId) { + const { layer } = Mota.require('@user/data-state').state; + const event = layer.getLayerByAlias('event'); + event.setBlock(0, x, y); + } }; ////// 一次性删除多个block ////// @@ -3419,6 +3439,11 @@ maps.prototype.setBlock = function (number, x, y, floorId, noredraw) { number, originBlock?.id ?? 0 ); + if (floorId === core.status.floorId) { + const { layer } = Mota.require('@user/data-state').state; + const event = layer.getLayerByAlias('event'); + event.setBlock(number, x, y); + } }; maps.prototype.animateSetBlock = function ( @@ -3620,6 +3645,11 @@ maps.prototype.replaceBlock = function (fromNumber, toNumber, floorId) { fromNumber, toNumber ); + if (floorId === core.status.floorId) { + const { layer } = Mota.require('@user/data-state').state; + const event = layer.getLayerByAlias('event'); + event.setBlock(toNumber, x, y); + } } }, this); if (floorId == core.status.floorId) core.redrawMap(); @@ -3669,6 +3699,11 @@ maps.prototype.setBgFgBlock = function (name, number, x, y, floorId) { y, floorId ); + if (floorId === core.status.floorId) { + const { layer } = Mota.require('@user/data-state').state; + const mapLayer = layer.getLayerByAlias(name); + mapLayer.setBlock(block.id, x, y); + } }; ////// 重置地图 //////