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