diff --git a/src/core/fx/canvas2d.ts b/src/core/fx/canvas2d.ts index 0e65bc9..56a0284 100644 --- a/src/core/fx/canvas2d.ts +++ b/src/core/fx/canvas2d.ts @@ -1,4 +1,5 @@ import { EventEmitter } from 'eventemitter3'; +import { logger } from '../common/logger'; interface OffscreenCanvasEvent { /** 当被动触发resize时(例如core.domStyle.scale变化、窗口大小变化)时触发,使用size函数并不会触发 */ @@ -26,6 +27,12 @@ export class MotaOffscreenCanvas2D extends EventEmitter { /** 更新标识符,如果发生变化则说明画布被动清空 */ symbol: number = 0; + private _freezed: boolean = false; + /** 当前画布是否被冻结 */ + get freezed() { + return this._freezed; + } + /** * 创建一个新的离屏画布 * @param alpha 是否启用透明度通道 @@ -33,6 +40,7 @@ export class MotaOffscreenCanvas2D extends EventEmitter { */ constructor(alpha: boolean = true, canvas?: HTMLCanvasElement) { super(); + // console.trace(); this.canvas = canvas ?? document.createElement('canvas'); this.ctx = this.canvas.getContext('2d', { alpha })!; @@ -46,6 +54,10 @@ export class MotaOffscreenCanvas2D extends EventEmitter { * 设置画布的大小 */ size(width: number, height: number) { + if (this._freezed) { + logger.warn(33); + return; + } let ratio = this.highResolution ? devicePixelRatio : 1; const scale = core.domStyle.scale; if (this.autoScale) { @@ -69,6 +81,10 @@ export class MotaOffscreenCanvas2D extends EventEmitter { * 设置当前画布是否跟随样板的 core.domStyle.scale 一同进行缩放 */ withGameScale(auto: boolean) { + if (this._freezed) { + logger.warn(33); + return; + } this.autoScale = auto; this.size(this.width, this.height); } @@ -77,6 +93,10 @@ export class MotaOffscreenCanvas2D extends EventEmitter { * 设置当前画布是否为高清画布 */ setHD(hd: boolean) { + if (this._freezed) { + logger.warn(33); + return; + } this.highResolution = hd; this.size(this.width, this.height); } @@ -85,6 +105,10 @@ export class MotaOffscreenCanvas2D extends EventEmitter { * 设置当前画布的抗锯齿设置 */ setAntiAliasing(anti: boolean) { + if (this._freezed) { + logger.warn(33); + return; + } this.antiAliasing = anti; this.ctx.imageSmoothingEnabled = anti; } @@ -93,6 +117,10 @@ export class MotaOffscreenCanvas2D extends EventEmitter { * 清空画布 */ clear() { + if (this._freezed) { + logger.warn(33); + return; + } this.ctx.save(); this.ctx.setTransform(1, 0, 0, 1, 0, 0); this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height); @@ -103,13 +131,21 @@ export class MotaOffscreenCanvas2D extends EventEmitter { * 删除这个画布 */ delete() { + this.canvas.remove(); + this.ctx.reset(); + this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height); + MotaOffscreenCanvas2D.list.delete(this); + } + + freeze() { + this._freezed = true; MotaOffscreenCanvas2D.list.delete(this); } /** * 复制一个离屏Canvas2D对象,一般用于缓存等操作 * @param canvas 被复制的MotaOffscreenCanvas2D对象 - * @returns 复制结果 + * @returns 复制结果,注意复制结果是被冻结的,无法进行大小等的修改,但是可以继续绘制 */ static clone(canvas: MotaOffscreenCanvas2D): MotaOffscreenCanvas2D { const newCanvas = new MotaOffscreenCanvas2D(); @@ -123,12 +159,13 @@ export class MotaOffscreenCanvas2D extends EventEmitter { canvas.width, canvas.height ); + newCanvas.freeze(); return newCanvas; } - static refreshAll() { + static refreshAll(force: boolean = false) { this.list.forEach(v => { - if (v.autoScale) { + if (force || v.autoScale) { v.size(v.width, v.height); v.symbol++; v.emit('resize'); diff --git a/src/core/render/cache.ts b/src/core/render/cache.ts index c86a747..c1f9940 100644 --- a/src/core/render/cache.ts +++ b/src/core/render/cache.ts @@ -480,6 +480,7 @@ function splitAutotiles(map: IdToNumber): AutotileCaches { master.size(32, 32); master.ctx.drawImage(img, 0, 0, 32, 32, 0, 0, 32, 32); masterMap[auto] = master.canvas.toDataURL('image/png'); + master.delete(); // 自动图块的绘制信息 for (let i = 0; i <= 0b11111111; i++) { @@ -504,6 +505,7 @@ function splitAutotiles(map: IdToNumber): AutotileCaches { canvas.setAntiAliasing(false); canvas.withGameScale(false); canvas.size(32 * frame, 32); + canvas.freeze(); const ctx = canvas.ctx; for (let i = 0; i < frame; i++) { const dx = 32 * i; @@ -525,16 +527,17 @@ function splitAutotiles(map: IdToNumber): AutotileCaches { } } + const judge = new MotaOffscreenCanvas2D(); + judge.setHD(false); + judge.setAntiAliasing(false); + judge.withGameScale(false); + judge.size(32, 32); // 进行父子关系判断 for (const [key, img] of Object.entries(core.material.images.autotile)) { const auto = map[key as AllIdsOf<'autotile'>]; // 只针对3*4的图块进行,截取第一行中间的,然后判断 - const judge = new MotaOffscreenCanvas2D(); - judge.setHD(false); - judge.setAntiAliasing(false); - judge.withGameScale(false); - judge.size(32, 32); + judge.clear(); judge.ctx.drawImage(img, 32, 0, 32, 32, 0, 0, 32, 32); const data = judge.canvas.toDataURL('image/png'); @@ -547,6 +550,7 @@ function splitAutotiles(map: IdToNumber): AutotileCaches { } } } + judge.delete(); return cache as AutotileCaches; } diff --git a/src/core/render/camera.ts b/src/core/render/camera.ts index d3e8026..63f254a 100644 --- a/src/core/render/camera.ts +++ b/src/core/render/camera.ts @@ -4,28 +4,28 @@ import { logger } from '../common/logger'; import { Transform } from './transform'; import EventEmitter from 'eventemitter3'; -export interface CameraTranslate { +export interface ICameraTranslate { readonly type: 'translate'; readonly from: Camera; x: number; y: number; } -export interface CameraRotate { +export interface ICameraRotate { readonly type: 'rotate'; readonly from: Camera; /** 旋转角,单位弧度 */ angle: number; } -export interface CameraScale { +export interface ICameraScale { readonly type: 'scale'; readonly from: Camera; x: number; y: number; } -type CameraOperation = CameraTranslate | CameraScale | CameraRotate; +type CameraOperation = ICameraTranslate | ICameraScale | ICameraRotate; interface CameraEvent { destroy: []; @@ -145,8 +145,8 @@ export class Camera extends EventEmitter { * 添加一个平移操作 * @returns 添加的平移变换操作 */ - addTranslate(): CameraTranslate { - const item: CameraTranslate = { + addTranslate(): ICameraTranslate { + const item: ICameraTranslate = { type: 'translate', x: 0, y: 0, @@ -160,8 +160,8 @@ export class Camera extends EventEmitter { * 添加一个旋转操作 * @returns 添加的旋转变换操作 */ - addRotate(): CameraRotate { - const item: CameraRotate = { + addRotate(): ICameraRotate { + const item: ICameraRotate = { type: 'rotate', angle: 0, from: this @@ -174,8 +174,8 @@ export class Camera extends EventEmitter { * 添加一个放缩操作 * @returns 添加的放缩变换操作 */ - addScale(): CameraScale { - const item: CameraScale = { + addScale(): ICameraScale { + const item: ICameraScale = { type: 'scale', x: 1, y: 1, @@ -213,7 +213,7 @@ export class Camera extends EventEmitter { * @param time 动画时长 */ applyTranslateAnimation( - operation: CameraTranslate, + operation: ICameraTranslate, animate: Animation, time: number ) { @@ -237,7 +237,7 @@ export class Camera extends EventEmitter { * @param time 动画时长 */ applyRotateAnimation( - operation: CameraRotate, + operation: ICameraRotate, animate: Animation, time: number ) { @@ -260,7 +260,7 @@ export class Camera extends EventEmitter { * @param time 动画时长 */ applyScaleAnimation( - operation: CameraScale, + operation: ICameraScale, animate: Animation, time: number ) { @@ -284,7 +284,7 @@ export class Camera extends EventEmitter { * @param time 渐变时长 */ applyTranslateTransition( - operation: CameraTranslate, + operation: ICameraTranslate, animate: Transition, time: number ) { @@ -308,7 +308,7 @@ export class Camera extends EventEmitter { * @param time 渐变时长 */ applyRotateTransition( - operation: CameraRotate, + operation: ICameraRotate, animate: Transition, time: number ) { @@ -331,7 +331,7 @@ export class Camera extends EventEmitter { * @param time 渐变时长 */ applyScaleTransition( - operation: CameraScale, + operation: ICameraScale, animate: Transition, time: number ) { @@ -514,7 +514,7 @@ export class CameraAnimation extends EventEmitter { * @param timing 动画的缓动函数 */ translate( - operation: CameraTranslate, + operation: ICameraTranslate, x: number, y: number, time: number, @@ -542,7 +542,7 @@ export class CameraAnimation extends EventEmitter { * @param timing 动画的缓动函数 */ rotate( - operation: CameraRotate, + operation: ICameraRotate, angle: number, time: number, start: number, @@ -568,7 +568,7 @@ export class CameraAnimation extends EventEmitter { * @param timing 动画的缓动函数 */ scale( - operation: CameraScale, + operation: ICameraScale, scale: number, time: number, start: number, diff --git a/src/core/render/gl2.ts b/src/core/render/gl2.ts index 380c26b..1d45d69 100644 --- a/src/core/render/gl2.ts +++ b/src/core/render/gl2.ts @@ -385,6 +385,7 @@ export abstract class GL2 extends RenderItem { destroy(): void { this.programs.forEach(v => v.destroy()); + this.canvas.remove(); super.destroy(); } diff --git a/src/core/render/item.ts b/src/core/render/item.ts index 2d67d13..097204d 100644 --- a/src/core/render/item.ts +++ b/src/core/render/item.ts @@ -462,6 +462,7 @@ export abstract class RenderItem this.remove(); this.emit('destroy'); this.removeAllListeners(); + this.cache.delete(); RenderItem.itemMap.delete(this._id); } } diff --git a/src/core/render/preset/block.ts b/src/core/render/preset/block.ts index c149264..8da2a94 100644 --- a/src/core/render/preset/block.ts +++ b/src/core/render/preset/block.ts @@ -1,5 +1,6 @@ import { EventEmitter } from '@/core/common/eventEmitter'; import { logger } from '@/core/common/logger'; +import { MotaOffscreenCanvas2D } from '@/core/fx/canvas2d'; interface BlockCacherEvent { split: () => void; @@ -16,13 +17,22 @@ interface BlockData { restHeight: number; } +export interface IBlockCacheable { + /** + * 摧毁这个缓存元素 + */ + destroy(): void; +} + /** * 简单分块缓存类,内容包含元素与分块两种,其中元素是最小单元,分块是缓存单元。 * 拿楼层举例,假如我将楼层按照13x13划分缓存,那么元素就是每个图块,而分块就是这13x13的缓存分块。 * 为方便区分,在相关函数的注释最后,都会有`xx -> yy`的说明, * 其中xx说明传入的数据是元素还是分块的数据,而yy表示其返回值或转换为的值 */ -export class BlockCacher extends EventEmitter { +export class BlockCacher< + T extends IBlockCacheable +> extends EventEmitter { /** 区域宽度 */ width: number; /** 区域高度 */ @@ -118,7 +128,12 @@ export class BlockCacher extends EventEmitter { const depth = this.cacheDepth; for (let i = 0; i < depth; i++) { if (deep & (1 << i)) { - this.cache.delete(index * this.cacheDepth + i); + const nowIndex = index * this.cacheDepth + i; + const item = this.cache.get(nowIndex); + if (item) { + item.destroy(); + this.cache.delete(nowIndex); + } } } } @@ -126,14 +141,19 @@ export class BlockCacher extends EventEmitter { /** * 清空指定索引的缓存,与 {@link clearCache} 不同的是,这里会直接清空对应索引的缓存,而不是指定分块的缓存(分块->void) */ - clearCacheByIndex(index: number) { - this.cache.delete(index); + clearCacheByIndex(index: number, func: (item: T) => void) { + const item = this.cache.get(index); + if (item) { + item.destroy(); + this.cache.delete(index); + } } /** * 清空所有缓存 */ clearAllCache() { + this.cache.forEach(v => v.destroy()); this.cache.clear(); } @@ -272,4 +292,24 @@ export class BlockCacher extends EventEmitter { (y + 1) * this.blockSize ]; } + + /** + * 摧毁这个块缓存 + */ + destroy() { + this.clearAllCache(); + } +} + +export interface ICanvasCacheItem extends IBlockCacheable { + readonly canvas: MotaOffscreenCanvas2D; + symbol: number; +} + +export class CanvasCacheItem implements ICanvasCacheItem { + constructor(public canvas: MotaOffscreenCanvas2D, public symbol: number) {} + + destroy(): void { + this.canvas.delete(); + } } diff --git a/src/core/render/preset/damage.ts b/src/core/render/preset/damage.ts index ee65ca2..c0d89d0 100644 --- a/src/core/render/preset/damage.ts +++ b/src/core/render/preset/damage.ts @@ -7,7 +7,12 @@ import { LayerGroup } from './layer'; import { ESpriteEvent, Sprite } from '../sprite'; -import { BlockCacher } from './block'; +import { + BlockCacher, + CanvasCacheItem, + IBlockCacheable, + ICanvasCacheItem +} from './block'; import type { DamageEnemy, EnemyCollection, @@ -16,7 +21,7 @@ import type { import { MotaOffscreenCanvas2D } from '@/core/fx/canvas2d'; import { isNil } from 'lodash-es'; import { getDamageColor } from '@/plugin/utils'; -import { transformCanvas } from '../item'; +import { RenderItem, transformCanvas } from '../item'; import EventEmitter from 'eventemitter3'; import { Transform } from '../transform'; @@ -120,11 +125,6 @@ export interface DamageRenderable { strokeWidth?: number; } -interface DamageCache { - canvas: MotaOffscreenCanvas2D; - symbol: number; -} - interface EDamageEvent extends ESpriteEvent { setMapSize: [width: number, height: number]; beforeDamageRender: [need: Set, transform: Transform]; @@ -132,11 +132,11 @@ interface EDamageEvent extends ESpriteEvent { dirtyUpdate: [block: number]; } -export class Damage extends Sprite { +export class Damage extends RenderItem { mapWidth: number = 0; mapHeight: number = 0; - block: BlockCacher; + block: BlockCacher; /** 键表示分块索引,值表示在这个分块上的渲染信息(当然实际渲染位置可以不在这个分块上) */ renderable: Map> = new Map(); @@ -147,8 +147,6 @@ export class Damage extends Sprite { /** 单元格大小 */ cellSize: number = 32; - /** 伤害渲染层 */ - damageMap: MotaOffscreenCanvas2D = new MotaOffscreenCanvas2D(); /** 默认伤害字体 */ font: string = '300 9px Verdana'; /** 默认描边样式,当伤害文字不存在描边属性时会使用此属性 */ @@ -165,18 +163,15 @@ export class Damage extends Sprite { this.block = new BlockCacher(0, 0, core._WIDTH_, 1); this.type = 'absolute'; this.size(core._PX_, core._PY_); - this.damageMap.withGameScale(true); - this.damageMap.setHD(true); - this.damageMap.setAntiAliasing(true); - this.damageMap.size(core._PX_, core._PY_); + this.setHD(true); + this.setAntiAliasing(true); + } - this.setRenderFn((canvas, transform) => { - const { ctx } = canvas; - const { width, height } = canvas; - ctx.imageSmoothingEnabled = false; - this.renderDamage(transform); - ctx.drawImage(this.damageMap.canvas, 0, 0, width, height); - }); + protected render( + canvas: MotaOffscreenCanvas2D, + transform: Transform + ): void { + this.renderDamage(canvas, transform); } private onExtract = () => { @@ -468,12 +463,10 @@ export class Damage extends Sprite { * 渲染伤害层 * @param transform 变换矩阵 */ - renderDamage(transform: Transform) { + renderDamage(canvas: MotaOffscreenCanvas2D, transform: Transform) { // console.time('damage'); - const { ctx } = this.damageMap; - ctx.save(); - this.damageMap.clear(); - transformCanvas(this.damageMap, transform); + const { ctx } = canvas; + transformCanvas(canvas, transform); // console.trace(); const render = this.calNeedRender(transform); @@ -529,10 +522,7 @@ export class Damage extends Sprite { }); ctx.drawImage(temp.canvas, px, py, size, size); - block.cache.set(v, { - canvas: temp, - symbol: temp.symbol - }); + block.cache.set(v, new CanvasCacheItem(temp, temp.symbol)); }); ctx.restore(); // console.timeEnd('damage'); @@ -540,6 +530,7 @@ export class Damage extends Sprite { destroy(): void { super.destroy(); + this.block.destroy(); this.enemy?.off('extract', this.onExtract); } } diff --git a/src/core/render/preset/layer.ts b/src/core/render/preset/layer.ts index 2b81044..3ec0294 100644 --- a/src/core/render/preset/layer.ts +++ b/src/core/render/preset/layer.ts @@ -5,7 +5,12 @@ import { TimingFn } from 'mutate-animate'; import { IAnimateFrame, renderEmits, RenderItem } from '../item'; import { logger } from '@/core/common/logger'; import { RenderableData, texture } from '../cache'; -import { BlockCacher } from './block'; +import { + BlockCacher, + CanvasCacheItem, + IBlockCacheable, + ICanvasCacheItem +} from './block'; import { Transform } from '../transform'; import { LayerFloorBinder, LayerGroupFloorBinder } from './floor'; import { RenderAdapter } from '../adapter'; @@ -388,7 +393,7 @@ export interface ILayerRenderExtends { * @param layer 目标Layer实例 * @param images 生成出的背景图块的单个分块图像,数组是因为背景图块可能是多帧图块 */ - onBackgroundGenerated?(layer: Layer, images: HTMLCanvasElement[]): void; + onBackgroundGenerated?(layer: Layer, images: MotaOffscreenCanvas2D[]): void; /** * 当修改渲染数据时执行的函数,参见 {@link Layer.putRenderData} @@ -504,11 +509,6 @@ export interface ILayerRenderExtends { onDestroy?(layer: Layer): void; } -interface LayerCacheItem { - symbol: number; - canvas: MotaOffscreenCanvas2D; -} - export interface LayerMovingRenderable extends RenderableData { zIndex: number; x: number; @@ -550,12 +550,17 @@ export class Layer extends Container { /** 背景图块 */ background: AllNumbers = 0; /** 背景图块画布 */ - backImage: HTMLCanvasElement[] = []; + backImage: MotaOffscreenCanvas2D[] = []; /** 背景贴图 */ floorImage: FloorAnimate[] = []; /** 分块信息 */ - block: BlockCacher = new BlockCacher(0, 0, core._WIDTH_, 4); + block: BlockCacher = new BlockCacher( + 0, + 0, + core._WIDTH_, + 4 + ); /** 大怪物渲染信息 */ bigImages: Map = new Map(); @@ -717,13 +722,17 @@ export class Layer extends Container { const num = this.background; const data = texture.getRenderable(num); + this.backImage.forEach(v => v.delete()); this.backImage = []; if (!data) return; const frame = data.frame; + const temp = new MotaOffscreenCanvas2D(); + temp.setHD(false); + temp.setAntiAliasing(false); + temp.withGameScale(false); for (let i = 0; i < frame; i++) { const canvas = new MotaOffscreenCanvas2D(); - const temp = new MotaOffscreenCanvas2D(); const ctx = canvas.ctx; const tempCtx = temp.ctx; const [sx, sy, w, h] = data.render[i]; @@ -731,9 +740,6 @@ export class Layer extends Container { canvas.setAntiAliasing(false); canvas.withGameScale(false); canvas.size(core._PX_, core._PY_); - temp.setHD(false); - temp.setAntiAliasing(false); - temp.withGameScale(false); temp.size(w, h); const img = data.autotile ? data.image[0b11111111] : data.image; @@ -743,8 +749,9 @@ export class Layer extends Container { ctx.fillStyle = pattern; ctx.fillRect(0, 0, canvas.width, canvas.height); - this.backImage.push(canvas.canvas); + this.backImage.push(canvas); } + temp.delete(); for (const ex of this.extend.values()) { ex.onBackgroundGenerated?.(this, this.backImage); @@ -1078,7 +1085,7 @@ export class Layer extends Container { const sx = x * blockSize; const sy = y * blockSize; ctx.drawImage( - img, + img.canvas, sx * cell, sy * cell, blockSize * cell, @@ -1180,10 +1187,7 @@ export class Layer extends Container { blockSize * cell, blockSize * cell ); - this.block.cache.set(index, { - canvas: temp, - symbol: temp.symbol - }); + this.block.cache.set(index, new CanvasCacheItem(temp, temp.symbol)); }); } @@ -1379,6 +1383,12 @@ export class Layer extends Container { ex.onDestroy?.(this); } super.destroy(); + this.staticMap.delete(); + this.movingMap.delete(); + this.backMap.delete(); + this.backImage.forEach(v => v.delete()); + this.block.destroy(); + this.main.destroy(); layerAdapter.remove(this); } diff --git a/src/core/render/render.ts b/src/core/render/render.ts index 5a9188b..555a5d9 100644 --- a/src/core/render/render.ts +++ b/src/core/render/render.ts @@ -78,7 +78,9 @@ export class MotaRenderer extends Container { } destroy() { + super.destroy(); MotaRenderer.list.delete(this.id); + this.target.delete(); } static get(id: string) { diff --git a/src/core/render/utils.ts b/src/core/render/utils.ts index 4a9afa0..4b19eb8 100644 --- a/src/core/render/utils.ts +++ b/src/core/render/utils.ts @@ -17,7 +17,7 @@ export function enableViewport() { /** * 将两个缓动函数做加法 */ -export function AddTiming(timing1: TimingFn, timing2: TimingFn): TimingFn { +export function addTiming(timing1: TimingFn, timing2: TimingFn): TimingFn { return (p: number) => timing1(p) + timing2(p); } diff --git a/src/data/logger.json b/src/data/logger.json index 40f5b9c..91b4ab5 100644 --- a/src/data/logger.json +++ b/src/data/logger.json @@ -57,6 +57,7 @@ "30": "Cannot use indices named $1 since no definition for it. Please define it in advance.", "31": "Cannot use indices since the indices instance is not belong to the program.", "32": "Sub-image exceeds texture dimensions, auto adjusting size.", + "33": "Cannot modify MotaOffscreenCanvas2D that is freezed.", "1001": "Item-detail extension needs 'floor-binder' and 'floor-damage' extension as dependency.", "1101": "Cannot add new effect to point effect instance, for there's no more reserve space for it. Please increase the max count of the instance." } diff --git a/src/module/weather/rain.ts b/src/module/weather/rain.ts index 44df2cf..99d8b68 100644 --- a/src/module/weather/rain.ts +++ b/src/module/weather/rain.ts @@ -2,9 +2,7 @@ import { Shader, ShaderProgram } from '@/core/render/shader'; import { IWeather, WeatherController } from './weather'; import { MotaRenderer } from '@/core/render/render'; import { Container } from '@/core/render/container'; -import { GL2Program, IShaderUniform, UniformType } from '@/core/render/gl2'; -import { MotaOffscreenCanvas2D } from '@/core/fx/canvas2d'; -import { Transform } from '@/core/render/transform'; +import { IShaderUniform, UniformType } from '@/core/render/gl2'; const rainVs = /* glsl */ ` in vec2 a_rainVertex; diff --git a/src/plugin/boss/towerBossProjectile.ts b/src/plugin/boss/towerBossProjectile.ts index 9961648..da3a325 100644 --- a/src/plugin/boss/towerBossProjectile.ts +++ b/src/plugin/boss/towerBossProjectile.ts @@ -163,8 +163,10 @@ export class ArrowProjectile extends Projectile { this.easing = void 0; this.dangerEasing = void 0; this.horizontal?.clear(); + this.horizontal?.delete(); this.horizontal = null; this.vertical?.clear(); + this.vertical?.delete(); this.vertical = null; } @@ -465,6 +467,7 @@ export class ThunderProjectile extends Projectile { static end() { this.cache?.clear(); + this.cache?.delete(); this.cache = null; } @@ -648,8 +651,10 @@ export class ThunderBallProjectile extends Projectile { static end() { this.dangerEasing = void 0; this.horizontal?.clear(); + this.horizontal?.delete(); this.horizontal = null; this.vertical?.clear(); + this.vertical?.delete(); this.vertical = null; } diff --git a/src/plugin/chase/chase.ts b/src/plugin/chase/chase.ts index d1e1826..63d103f 100644 --- a/src/plugin/chase/chase.ts +++ b/src/plugin/chase/chase.ts @@ -337,6 +337,8 @@ export class Chase extends EventEmitter { Chase.shader.remove(); this.emit('end', success); this.removeAllListeners(); + this.pathMap.forEach(v => v.delete()); + this.pathMap.clear(); } } diff --git a/src/plugin/chase/chase1.ts b/src/plugin/chase/chase1.ts index a4a5951..58e9dab 100644 --- a/src/plugin/chase/chase1.ts +++ b/src/plugin/chase/chase1.ts @@ -1,7 +1,7 @@ import { Animation, hyper, linear, power, sleep } from 'mutate-animate'; import { Chase, ChaseData, IChaseController } from './chase'; import { completeAchievement } from '../ui/achievement'; -import { Camera, CameraAnimation, CameraScale } from '@/core/render/camera'; +import { Camera, CameraAnimation, ICameraScale } from '@/core/render/camera'; import { LayerGroup } from '@/core/render/preset/layer'; import { MotaRenderer } from '@/core/render/render'; import { Sprite } from '@/core/render/sprite'; @@ -272,7 +272,7 @@ function playAudio(from: number, chase: Chase) { function processScale( chase: Chase, ani: Animation, - scale: CameraScale, + scale: ICameraScale, camera: Camera ) { chase.onceLoc(35, 3, 'MT15', () => {