From fc05ddec9bf67711f16dafab7f502983d988edce Mon Sep 17 00:00:00 2001 From: unanmed <1319491857@qq.com> Date: Thu, 22 Aug 2024 23:29:15 +0800 Subject: [PATCH] =?UTF-8?q?refactor:=20=E4=BC=98=E5=8C=96=E6=B8=B2?= =?UTF-8?q?=E6=9F=93=E7=BC=93=E5=AD=98=20&=20=E6=B7=BB=E5=8A=A0=E6=AF=8F?= =?UTF-8?q?=E4=B8=AA=E5=85=83=E7=B4=A0=E7=9A=84Transform?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/core/fx/canvas2d.ts | 4 +- src/core/index.ts | 2 - src/core/main/custom/hotkey.ts | 4 +- src/core/render/container.ts | 86 ++------ src/core/render/item.ts | 213 ++++++++------------ src/core/render/preset/damage.ts | 48 +++-- src/core/render/preset/floor.ts | 4 + src/core/render/preset/hero.ts | 1 - src/core/render/preset/layer.ts | 144 +++++-------- src/core/render/preset/misc.ts | 18 +- src/core/render/render.ts | 120 +++++------ src/core/render/sprite.ts | 65 ++---- src/core/render/{camera.ts => transform.ts} | 81 +++++--- src/game/index.ts | 4 + src/game/system.ts | 4 + src/plugin/game/fallback.ts | 2 - 16 files changed, 317 insertions(+), 483 deletions(-) rename src/core/render/{camera.ts => transform.ts} (66%) diff --git a/src/core/fx/canvas2d.ts b/src/core/fx/canvas2d.ts index edbe320..9323326 100644 --- a/src/core/fx/canvas2d.ts +++ b/src/core/fx/canvas2d.ts @@ -1,10 +1,10 @@ import { parseCss } from '@/plugin/utils'; -import { EventEmitter } from '../common/eventEmitter'; +import { EventEmitter } from 'eventemitter3'; import { CSSObj } from '../interface'; interface OffscreenCanvasEvent { /** 当被动触发resize时(例如core.domStyle.scale变化、窗口大小变化)时触发,使用size函数并不会触发 */ - resize: () => void; + resize: []; } export class MotaOffscreenCanvas2D extends EventEmitter { diff --git a/src/core/index.ts b/src/core/index.ts index 0b56f3e..8bc99ed 100644 --- a/src/core/index.ts +++ b/src/core/index.ts @@ -65,7 +65,6 @@ import * as portal from './fx/portal'; import { MotaRenderer } from './render/render'; import { Container } from './render/container'; import { Sprite } from './render/sprite'; -import { Camera } from './render/camera'; import { Image, Text } from './render/preset/misc'; import { RenderItem } from './render/item'; import { texture } from './render/cache'; @@ -152,7 +151,6 @@ Mota.register('module', 'Render', { MotaRenderer, Container, Sprite, - Camera, Text, Image, RenderItem, diff --git a/src/core/main/custom/hotkey.ts b/src/core/main/custom/hotkey.ts index 0cb6b96..f0417ac 100644 --- a/src/core/main/custom/hotkey.ts +++ b/src/core/main/custom/hotkey.ts @@ -422,7 +422,9 @@ document.addEventListener('keyup', e => { const code = keycode(e.keyCode); if (gameKey.emitKey(code, assist, 'up', e)) { e.preventDefault(); - deleteWith(core.status.holdingKeys, e.keyCode); + if (core.status.holdingKeys) { + deleteWith(core.status.holdingKeys, e.keyCode); + } } else { // polyfill样板 if ( diff --git a/src/core/render/container.ts b/src/core/render/container.ts index 386cee0..1a02c7b 100644 --- a/src/core/render/container.ts +++ b/src/core/render/container.ts @@ -1,95 +1,51 @@ import { MotaOffscreenCanvas2D } from '../fx/canvas2d'; -import { Camera } from './camera'; -import { - ICanvasCachedRenderItem, - IRenderChildable, - RenderItem, - RenderItemPosition, - withCacheRender -} from './item'; +import { IRenderChildable, RenderItem, RenderItemPosition } from './item'; +import { Transform } from './transform'; -export class Container - extends RenderItem - implements ICanvasCachedRenderItem, IRenderChildable -{ +export class Container extends RenderItem implements IRenderChildable { children: RenderItem[] = []; sortedChildren: RenderItem[] = []; - canvas: MotaOffscreenCanvas2D; - - /** 是否启用缓存机制,对于特殊场景,内部已经包含了缓存机制,这时就不需要启用了 */ - private readonly enableCache: boolean; - /** * 创建一个容器,容器中可以包含其他渲染对象 - * @param type 渲染模式,absolute表示绝对位置,static表示跟随摄像机移动,只对顶层元素有效 + * @param type 渲染模式,absolute表示绝对位置,static表示跟随摄像机移动 * @param cache 是否启用缓存机制 */ constructor(type: RenderItemPosition = 'static', cache: boolean = true) { - super(); - this.canvas = new MotaOffscreenCanvas2D(); + super(cache); this.type = type; - this.canvas.withGameScale(true); - this.enableCache = cache; } - private renderTo(canvas: MotaOffscreenCanvas2D, camera: Camera) { + protected render( + canvas: MotaOffscreenCanvas2D, + transform: Transform + ): void { const { ctx } = canvas; this.sortedChildren.forEach(v => { if (v.hidden) return; ctx.save(); - if (!v.antiAliasing) { - ctx.imageSmoothingEnabled = false; - } else { + if (v.antiAliasing) { ctx.imageSmoothingEnabled = true; + } else { + ctx.imageSmoothingEnabled = false; } - v.render(canvas, camera); + v.renderContent(canvas, transform); ctx.restore(); }); } - render(canvas: MotaOffscreenCanvas2D, camera: Camera): void { - this.emit('beforeRender'); - if (this.needUpdate) { - this.cache(this.using); - this.needUpdate = false; - } - if (this.enableCache) { - withCacheRender(this, canvas.canvas, canvas.ctx, camera, c => { - this.renderTo(c, camera); - }); - } else { - this.renderTo(canvas, camera); - } - this.writing = void 0; - this.emit('afterRender'); - } - - size(width: number, height: number) { - this.width = width; - this.height = height; - this.canvas.size(width, height); - this.writing = this.using; - this.update(this); - } - - pos(x: number, y: number) { - this.x = x; - this.y = y; - } - /** * 添加子元素到这个容器上,然后在下一个tick执行更新 * @param children 要添加的子元素 */ - appendChild(...children: RenderItem[]) { + appendChild(...children: RenderItem[]) { children.forEach(v => (v.parent = this)); this.children.push(...children); this.sortChildren(); this.update(this); } - removeChild(...child: RenderItem[]): void { + removeChild(...child: RenderItem[]): void { child.forEach(v => { const index = this.children.indexOf(v); if (index === -1) return; @@ -105,18 +61,6 @@ export class Container .sort((a, b) => a.zIndex - b.zIndex); } - setHD(hd: boolean): void { - this.highResolution = hd; - this.canvas.setHD(hd); - this.update(this); - } - - setAntiAliasing(anti: boolean): void { - this.antiAliasing = anti; - this.canvas.setAntiAliasing(anti); - this.update(this); - } - destroy(): void { super.destroy(); this.children.forEach(v => { diff --git a/src/core/render/item.ts b/src/core/render/item.ts index acf92e0..105f18d 100644 --- a/src/core/render/item.ts +++ b/src/core/render/item.ts @@ -1,43 +1,16 @@ import { isNil } from 'lodash-es'; import { EventEmitter } from 'eventemitter3'; import { MotaOffscreenCanvas2D } from '../fx/canvas2d'; -import { Camera } from './camera'; import { Ticker, TickerFn } from 'mutate-animate'; +import { Transform } from './transform'; export type RenderFunction = ( canvas: MotaOffscreenCanvas2D, - camera: Camera + transform: Transform ) => void; export type RenderItemPosition = 'absolute' | 'static'; -interface IRenderCache { - /** 缓存列表 */ - cacheList: Map; - /** 当前正在使用的缓存 */ - using?: string; - /** 下次绘制需要写入的缓存 */ - writing?: string; - - /** - * 在之后的绘制中使用缓存,如果缓存不存在,那么就不使用缓存,并在下一次绘制结束后写入 - * @param index 缓存的索引,不填时表示不使用缓存 - */ - useCache(index?: string): void; - - /** - * 将下次绘制写入缓存并使用 - * @param index 缓存的索引,不填时表示不进行缓存 - */ - cache(index?: string): void; - - /** - * 清除指定或所有缓存 - * @param index 要清除的缓存,不填代表清除所有 - */ - clearCache(index?: string): void; -} - export interface IRenderUpdater { /** * 更新这个渲染元素 @@ -46,11 +19,6 @@ export interface IRenderUpdater { update(item?: RenderItem): void; } -export interface ICanvasCachedRenderItem { - /** 离屏画布,首先渲染到它上面,然后由Renderer渲染到最终画布上 */ - canvas: MotaOffscreenCanvas2D; -} - interface IRenderAnchor { anchorX: number; anchorY: number; @@ -89,13 +57,13 @@ export interface IRenderChildable { * 向这个元素添加子元素 * @param child 添加的元素 */ - appendChild(...child: RenderItem[]): void; + appendChild(...child: RenderItem[]): void; /** * 移除这个元素中的某个子元素 * @param child 要移除的元素 */ - removeChild(...child: RenderItem[]): void; + removeChild(...child: RenderItem[]): void; /** * 对子元素进行排序 @@ -142,11 +110,11 @@ interface IRenderTickerSupport { removeTicker(id: number, callEnd?: boolean): boolean; } -interface RenderItemEvent { - beforeUpdate: (item?: RenderItem) => void; - afterUpdate: (item?: RenderItem) => void; - beforeRender: () => void; - afterRender: () => void; +export interface ERenderItemEvent { + beforeUpdate: [item?: RenderItem]; + afterUpdate: [item?: RenderItem]; + beforeRender: [transform: Transform]; + afterRender: [transform: Transform]; } interface TickerDelegation { @@ -158,11 +126,9 @@ const beforeFrame: (() => void)[] = []; const afterFrame: (() => void)[] = []; const renderFrame: (() => void)[] = []; -// todo: 添加模型变换 -export abstract class RenderItem - extends EventEmitter +export abstract class RenderItem + extends EventEmitter implements - IRenderCache, IRenderUpdater, IRenderAnchor, IRenderConfig, @@ -178,22 +144,17 @@ export abstract class RenderItem /** ticker委托id */ static tickerId: number = 0; + /** 元素纵深,表示了遮挡关系 */ zIndex: number = 0; - x: number = 0; - y: number = 0; width: number = 200; height: number = 200; - cacheList: Map = new Map(); - - using?: string; - writing?: string; - + // 渲染锚点,(0,0)表示左上角,(1,1)表示右下角 anchorX: number = 0; anchorY: number = 0; - /** 渲染模式,absolute表示绝对位置,static表示跟随摄像机移动,只对顶层元素有效 */ + /** 渲染模式,absolute表示绝对位置,static表示跟随摄像机移动 */ type: 'absolute' | 'static' = 'static'; /** 是否是高清画布 */ highResolution: boolean = true; @@ -202,57 +163,92 @@ export abstract class RenderItem /** 是否被隐藏 */ hidden: boolean = false; + /** 当前元素的父元素 */ parent?: RenderItem & IRenderChildable; protected needUpdate: boolean = false; - constructor() { + /** 该渲染元素的模型变换矩阵 */ + transform: Transform = new Transform(); + + /** 渲染缓存信息 */ + private cache: MotaOffscreenCanvas2D = new MotaOffscreenCanvas2D(); + /** 是否需要更新缓存 */ + private cacheDirty: boolean = true; + /** 是否启用缓存机制 */ + readonly enableCache: boolean = true; + + constructor(enableCache: boolean = true) { super(); - // this.using = '@default'; + this.enableCache = enableCache; + this.cache.withGameScale(true); } /** - * 渲染这个对象 + * 渲染函数 * @param canvas 渲染至的画布 - * @param camera 渲染时使用的摄像机 + * @param transform 当前变换矩阵的,渲染时已经进行变换处理,不需要对画布再次进行变换处理 + * 此参数可用于自己对元素进行变换处理,也会用于对子元素的处理。 + * 例如对于`absolute`类型的元素,同时有对视角改变的需求,就可以通过此参数进行变换。 + * 样板内置的`Layer`及`Damage`元素就是通过此方式实现的 */ - abstract render(canvas: MotaOffscreenCanvas2D, camera: Camera): void; + protected abstract render( + canvas: MotaOffscreenCanvas2D, + transform: Transform + ): void; /** * 修改这个对象的大小 */ - abstract size(width: number, height: number): void; + size(width: number, height: number): void { + this.width = width; + this.height = height; + this.cache.size(width, height); + this.cacheDirty = true; + this.update(this); + } /** - * 修改这个对象的位置 + * 渲染当前对象 + * @param canvas 渲染至的画布 + * @param transform 父元素的变换矩阵 */ - abstract pos(x: number, y: number): void; + renderContent(canvas: MotaOffscreenCanvas2D, transform: Transform) { + if (this.hidden) return; + this.emit('beforeRender', transform); + this.needUpdate = false; + const tran = transform.multiply(this.transform); + const ax = -this.anchorX * this.width; + const ay = -this.anchorY * this.height; + if (this.enableCache) { + if (this.cacheDirty) { + const cache = this.cache; + this.render(cache, tran); + this.cache = cache; + this.cacheDirty = false; + } - useCache(index?: string): void { - if (isNil(index)) { - this.using = void 0; - return; - } - if (!this.cacheList.has(index)) { - this.writing = index; - } - this.using = index; - } - - cache(index?: string): void { - this.writing = index; - this.using = index; - } - - clearCache(index?: string): void { - if (isNil(index)) { - this.writing = void 0; - this.using = void 0; - this.cacheList.clear(); + canvas.ctx.save(); + if (this.type === 'static') transformCanvas(canvas, tran); + canvas.ctx.drawImage(this.cache.canvas, ax, ay); + canvas.ctx.restore(); } else { - this.cacheList.delete(index); + canvas.ctx.save(); + if (this.type === 'static') transformCanvas(canvas, tran); + this.render(canvas, tran); + canvas.ctx.restore(); } + this.emit('afterRender', transform); + } + + /** + * 设置这个元素的位置,等效于`transform.setTranslate(x, y)` + * @param x 横坐标 + * @param y 纵坐标 + */ + pos(x: number, y: number) { + this.transform.setTranslate(x, y); } setAnchor(x: number, y: number): void { @@ -260,19 +256,22 @@ export abstract class RenderItem this.anchorY = y; } - update(item?: RenderItem): void { + update(item?: RenderItem): void { if (this.needUpdate) return; this.needUpdate = true; + this.cacheDirty = true; this.parent?.update(item); } setHD(hd: boolean): void { this.highResolution = hd; + this.cache.setHD(hd); this.update(this); } setAntiAliasing(anti: boolean): void { this.antiAliasing = anti; + this.cache.setAntiAliasing(anti); this.update(this); } @@ -429,54 +428,13 @@ Mota.require('var', 'hook').once('reset', () => { }); }); -export function withCacheRender( - item: RenderItem & ICanvasCachedRenderItem, - _canvas: HTMLCanvasElement, - ctx: CanvasRenderingContext2D, - camera: Camera, - fn: RenderFunction -) { - const { width, height } = item; - const ax = width * item.anchorX; - const ay = height * item.anchorY; - let write = item.writing; - if (!isNil(item.using) && isNil(item.writing)) { - const cache = item.cacheList.get(item.using); - if (cache) { - ctx.drawImage( - cache.canvas, - item.x - ax, - item.y - ay, - item.width, - item.height - ); - return; - } - write = item.using; - } - const { canvas: c, ctx: ct } = item.canvas; - ct.clearRect(0, 0, c.width, c.height); - fn(item.canvas, camera); - if (!isNil(write)) { - const cache = item.cacheList.get(write); - if (cache) { - const { canvas, ctx } = cache; - ctx.drawImage(c, 0, 0, canvas.width, canvas.height); - } else { - item.cacheList.set(write, MotaOffscreenCanvas2D.clone(item.canvas)); - } - } - - ctx.drawImage(c, item.x - ax, item.y - ay, item.width, item.height); -} - export function transformCanvas( canvas: MotaOffscreenCanvas2D, - camera: Camera, + transform: Transform, clear: boolean = false ) { const { canvas: ca, ctx, scale } = canvas; - const mat = camera.mat; + const mat = transform.mat; const a = mat[0] * scale; const b = mat[1] * scale; const c = mat[3] * scale; @@ -487,6 +445,5 @@ export function transformCanvas( if (clear) { ctx.clearRect(0, 0, ca.width, ca.height); } - ctx.translate(ca.width / 2, ca.height / 2); ctx.transform(a, b, c, d, e, f); } diff --git a/src/core/render/preset/damage.ts b/src/core/render/preset/damage.ts index 7a1e55b..bcbc94b 100644 --- a/src/core/render/preset/damage.ts +++ b/src/core/render/preset/damage.ts @@ -6,7 +6,7 @@ import { Layer, LayerGroup } from './layer'; -import { Sprite } from '../sprite'; +import { ESpriteEvent, Sprite } from '../sprite'; import { BlockCacher } from './block'; import type { DamageEnemy, @@ -14,22 +14,28 @@ import type { MapDamage } from '@/game/enemy/damage'; import { MotaOffscreenCanvas2D } from '@/core/fx/canvas2d'; -import { Camera } from '../camera'; import { isNil } from 'lodash-es'; import { getDamageColor } from '@/plugin/utils'; import { transformCanvas } from '../item'; +import EventEmitter from 'eventemitter3'; +import { Transform } from '../transform'; const ensureFloorDamage = Mota.require('fn', 'ensureFloorDamage'); -export class FloorDamageExtends implements ILayerGroupRenderExtends { +interface EFloorDamageEvent { + update: [floor: FloorIds]; +} + +export class FloorDamageExtends + extends EventEmitter + implements ILayerGroupRenderExtends +{ id: string = 'floor-damage'; floorBinder!: LayerGroupFloorBinder; group!: LayerGroup; sprite!: Damage; - static listenedDamage: Set = new Set(); - /** * 立刻刷新伤害渲染 */ @@ -41,6 +47,7 @@ export class FloorDamageExtends implements ILayerGroupRenderExtends { const enemy = core.status.maps[floor].enemy; this.sprite.updateCollection(enemy); + this.emit('update', floor); } /** @@ -89,18 +96,16 @@ export class FloorDamageExtends implements ILayerGroupRenderExtends { ); group.removeExtends('floor-damage'); } - FloorDamageExtends.listenedDamage.add(this); }); } onDestroy(group: LayerGroup): void { this.floorBinder.off('update', this.onUpdate); this.floorBinder.off('setBlock', this.onSetBlock); - FloorDamageExtends.listenedDamage.delete(this); } } -interface DamageRenderable { +export interface DamageRenderable { x: number; y: number; align: CanvasTextAlign; @@ -117,7 +122,12 @@ interface DamageCache { symbol: number; } -export class Damage extends Sprite { +interface EDamageEvent extends ESpriteEvent { + setMapSize: [width: number, height: number]; + beforeDamageRender: [need: Set, transform: Transform]; +} + +export class Damage extends Sprite { mapWidth: number = 0; mapHeight: number = 0; @@ -188,6 +198,8 @@ export class Damage extends Sprite { this.blockData.set(i, new Map()); this.renderable.set(i, new Set()); } + + this.emit('setMapSize', width, height); } /** @@ -385,32 +397,34 @@ export class Damage extends Sprite { /** * 计算需要渲染哪些块 */ - calNeedRender(camera: Camera) { + calNeedRender(transform: Transform) { if (this.parent instanceof LayerGroup) { // 如果处于地图组中,每个地图的渲染区域应该是一样的,因此可以缓存优化 - return this.parent.cacheNeedRender(camera, this.block); + return this.parent.cacheNeedRender(transform, this.block); } else if (this.parent instanceof Layer) { // 如果是地图的子元素,直接调用Layer的计算函数 - return this.parent.calNeedRender(camera); + return this.parent.calNeedRender(transform); } else { - return calNeedRenderOf(camera, this.cellSize, this.block); + return calNeedRenderOf(transform, this.cellSize, this.block); } } /** * 渲染伤害层 - * @param camera 摄像机 + * @param transform 变换矩阵 */ - renderDamage(camera: Camera) { + renderDamage(transform: Transform) { // console.time('damage'); const { ctx } = this.damageMap; ctx.save(); - transformCanvas(this.damageMap, camera, true); + transformCanvas(this.damageMap, transform, true); - const { res: render } = this.calNeedRender(camera); + const { res: render } = this.calNeedRender(transform); const block = this.block; const cell = this.cellSize; const size = cell * block.blockSize; + + this.emit('beforeDamageRender', render, transform); render.forEach(v => { const [x, y] = block.getBlockXYByIndex(v); const bx = x * block.blockSize; diff --git a/src/core/render/preset/floor.ts b/src/core/render/preset/floor.ts index fbfd865..95f2f18 100644 --- a/src/core/render/preset/floor.ts +++ b/src/core/render/preset/floor.ts @@ -107,6 +107,10 @@ export class LayerGroupFloorBinder this.emit('update', floor); } + getFloor() { + return this.bindThisFloor ? core.status.floorId : this.floor!; + } + /** * 设置图块 */ diff --git a/src/core/render/preset/hero.ts b/src/core/render/preset/hero.ts index b47c633..4a5400c 100644 --- a/src/core/render/preset/hero.ts +++ b/src/core/render/preset/hero.ts @@ -338,7 +338,6 @@ export class HeroRenderer this.moveId = layer.delegateTicker(() => { this.moveTick(Date.now()); }); - console.log(this); } onDestroy(layer: Layer): void { diff --git a/src/core/render/preset/layer.ts b/src/core/render/preset/layer.ts index e6baeb2..c085471 100644 --- a/src/core/render/preset/layer.ts +++ b/src/core/render/preset/layer.ts @@ -1,18 +1,13 @@ import { MotaOffscreenCanvas2D } from '@/core/fx/canvas2d'; import { Container } from '../container'; import { Sprite } from '../sprite'; -import { Camera } from '../camera'; import { TimingFn } from 'mutate-animate'; -import { - IAnimateFrame, - renderEmits, - RenderItem, - transformCanvas -} from '../item'; +import { IAnimateFrame, renderEmits, RenderItem } from '../item'; import { logger } from '@/core/common/logger'; -import { AutotileRenderable, RenderableData, texture } from '../cache'; +import { RenderableData, texture } from '../cache'; import { glMatrix } from 'gl-matrix'; import { BlockCacher } from './block'; +import { Transform } from '../transform'; export interface ILayerGroupRenderExtends { /** 拓展的唯一标识符 */ @@ -58,13 +53,6 @@ export interface ILayerGroupRenderExtends { */ onEmptyLayer?(group: LayerGroup): void; - /** - * 当渲染数据更新时执行的函数 - * @param group 目标LayerGroup实例 - * @param floor 数据更新的楼层 - */ - // onDataUpdate?: (group: LayerGroup, floor: FloorIds) => void; - /** * 当帧动画更新时执行的函数,例如从第一帧变成第二帧时 * @param group 目标LayerGroup实例 @@ -72,13 +60,6 @@ export interface ILayerGroupRenderExtends { */ onFrameUpdate?(group: LayerGroup, frame: number): void; - /** - * 当绑定楼层时执行的函数 - * @param group 目标LayerGroup实例 - * @param floor 绑定的楼层id,为空时表示绑定为当前楼层 - */ - // onBindFloor?: (group: LayerGroup, floor?: FloorIds) => void; - /** * 当拓展被取消挂载时执行的函数(LayerGroup被销毁,拓展被移除等) * @param group 目标LayerGroup实例 @@ -267,13 +248,13 @@ export class LayerGroup extends Container implements IAnimateFrame { /** * 缓存计算应该渲染的块 - * @param camera 摄像机 + * @param transform 变换矩阵 * @param blockData 分块信息 */ - cacheNeedRender(camera: Camera, block: BlockCacher) { + cacheNeedRender(transform: Transform, block: BlockCacher) { return ( this.needRender ?? - (this.needRender = calNeedRenderOf(camera, this.cellSize, block)) + (this.needRender = calNeedRenderOf(transform, this.cellSize, block)) ); } @@ -288,9 +269,6 @@ export class LayerGroup extends Container implements IAnimateFrame { * 更新动画帧 */ updateFrameAnimate() { - this.layers.forEach(v => { - v.cache(v.using); - }); this.update(this); for (const ex of this.extend.values()) { @@ -308,7 +286,7 @@ export class LayerGroup extends Container implements IAnimateFrame { } export function calNeedRenderOf( - camera: Camera, + transform: Transform, cell: number, block: BlockCacher ): NeedRenderData { @@ -317,10 +295,10 @@ export function calNeedRenderOf( const size = block.blockSize; // -1是因为宽度是core._PX_,从0开始的话,末尾索引就是core._PX_ - 1 - const [x1, y1] = Camera.untransformed(camera, -w, -h); - const [x2, y2] = Camera.untransformed(camera, w - 1, -h); - const [x3, y3] = Camera.untransformed(camera, w - 1, h - 1); - const [x4, y4] = Camera.untransformed(camera, -w, h - 1); + const [x1, y1] = Transform.untransformed(transform, -w, -h); + const [x2, y2] = Transform.untransformed(transform, w - 1, -h); + const [x3, y3] = Transform.untransformed(transform, w - 1, h - 1); + const [x4, y4] = Transform.untransformed(transform, -w, h - 1); const res: Set = new Set(); /** 一个纵坐标对应的所有横坐标,用于填充 */ @@ -469,8 +447,6 @@ export interface ILayerRenderExtends { */ onBackgroundSet?(layer: Layer, background: AllNumbers): void; - // onBackgroundBind?: (layer: Layer, floorId: FloorIds) => void; - /** * 当背景图块图片被生成时执行的函数 * @param layer 目标Layer实例 @@ -568,18 +544,26 @@ export interface ILayerRenderExtends { /** * 在地图渲染之前执行的函数 * @param layer 目标Layer实例 - * @param camera 渲染的摄像头信息 + * @param transform 渲染的变换矩阵 * @param need 需要渲染的分块信息 */ - onBeforeRender?(layer: Layer, camera: Camera, need: NeedRenderData): void; + onBeforeRender?( + layer: Layer, + transform: Transform, + need: NeedRenderData + ): void; /** * 在地图渲染之后执行的函数 * @param layer 目标Layer实例 - * @param camera 渲染的摄像头信息 + * @param transform 渲染的变换矩阵 * @param need 需要渲染的分块信息 */ - onAfterRender?(layer: Layer, camera: Camera, need: NeedRenderData): void; + onAfterRender?( + layer: Layer, + transform: Transform, + need: NeedRenderData + ): void; /** * 当拓展被取消挂载时执行的函数(Layer被销毁,拓展被移除等) @@ -606,38 +590,6 @@ interface NeedRenderData { back: [x: number, y: number][]; } -interface MovingStepLinearSwap { - /** 线性差值移动(也就是平移)或者是瞬移 */ - type: 'linear' | 'swap'; - x: number; - y: number; - /** 这次移动的总时长,不是每格时长 */ - time?: number; -} - -interface MovingStepFunction { - /** 自定义移动方式 */ - type: 'fn'; - /** - * 移动函数,返回一个三元素数组,表示当前所在格子数,以及在纵向上的深度(一般图块的深度就是它的纵坐标), - * 注意不是像素数,可以是小数 - */ - fn: TimingFn<3>; - time?: number; - relative?: boolean; -} - -interface MovingBlock { - /** 当前横坐标 */ - x: number; - /** 当前纵坐标 */ - y: number; - /** 渲染信息 */ - render: RenderableData | AutotileRenderable; - /** 当前的纵深 */ - nowZ: number; -} - export class Layer extends Container { // 一些会用到的常量 static readonly FRAME_0 = 1; @@ -654,7 +606,7 @@ export class Layer extends Container { protected backMap: MotaOffscreenCanvas2D = new MotaOffscreenCanvas2D(); /** 最终渲染至的Sprite */ - main: Sprite = new Sprite(); + main: Sprite = new Sprite('static', false); /** 渲染的层 */ layer?: FloorLayer; @@ -714,13 +666,13 @@ export class Layer extends Container { this.main.size(core._PX_, core._PY_); this.appendChild(this.main); - this.main.setRenderFn((canvas, camera) => { + this.main.setRenderFn((canvas, transform) => { const { ctx } = canvas; const { width, height } = canvas.canvas; ctx.save(); ctx.imageSmoothingEnabled = false; - const need = this.calNeedRender(camera); - this.renderMap(camera, need); + const need = this.calNeedRender(transform); + this.renderMap(transform, need); ctx.setTransform(1, 0, 0, 1, 0, 0); ctx.drawImage(this.backMap.canvas, 0, 0, width, height); ctx.drawImage(this.staticMap.canvas, 0, 0, width, height); @@ -930,8 +882,6 @@ export class Layer extends Container { this.updateBlocks(x, y, width, height); this.updateBigImages(x, y, width, height); - // this.update(this); - for (const ex of this.extend.values()) { ex.onDataPut?.(this, data, width, x, y, calAutotile); } @@ -1109,15 +1059,15 @@ export class Layer extends Container { } /** - * 计算在传入的摄像机的视角下,应该渲染哪些内容 - * @param camera 摄像机 + * 计算在传入的变换矩阵下,应该渲染哪些内容 + * @param transform 变换矩阵 */ - calNeedRender(camera: Camera): NeedRenderData { + calNeedRender(transform: Transform): NeedRenderData { if (this.parent instanceof LayerGroup) { // 如果处于地图组中,每个地图的渲染区域应该是一样的,因此可以缓存优化 - return this.parent.cacheNeedRender(camera, this.block); + return this.parent.cacheNeedRender(transform, this.block); } else { - return calNeedRenderOf(camera, this.cellSize, this.block); + return calNeedRenderOf(transform, this.cellSize, this.block); } } @@ -1138,7 +1088,7 @@ export class Layer extends Container { /** * 渲染当前地图 */ - renderMap(camera: Camera, need: NeedRenderData) { + renderMap(transform: Transform, need: NeedRenderData) { this.staticMap.clear(); this.movingMap.clear(); this.backMap.clear(); @@ -1146,32 +1096,31 @@ export class Layer extends Container { if (this.needUpdateMoving) this.updateMovingRenderable(); for (const ex of this.extend.values()) { - ex.onBeforeRender?.(this, camera, need); + ex.onBeforeRender?.(this, transform, need); } - this.renderBack(camera, need); - this.renderStatic(camera, need); - this.renderMoving(camera); + this.renderBack(transform, need); + this.renderStatic(transform, need); + this.renderMoving(transform); for (const ex of this.extend.values()) { - ex.onAfterRender?.(this, camera, need); + ex.onAfterRender?.(this, transform, need); } } /** * 渲染背景图 - * @param camera 摄像机 + * @param transform 变换矩阵 * @param need 需要渲染的块 */ - protected renderBack(camera: Camera, need: NeedRenderData) { + protected renderBack(transform: Transform, need: NeedRenderData) { const cell = this.cellSize; const frame = (RenderItem.animatedFrame % 4) + 1; const blockSize = this.block.blockSize; const { back } = need; const { ctx } = this.backMap; - const mat = camera.mat; + const mat = transform.mat; const [a, b, , c, d, , e, f] = mat; ctx.setTransform(1, 0, 0, 1, 0, 0); - ctx.translate(core._PX_ / 2, core._PY_ / 2); ctx.transform(a, b, c, d, e, f); if (this.background !== 0) { @@ -1195,7 +1144,7 @@ export class Layer extends Container { /** * 渲染静态层 */ - protected renderStatic(camera: Camera, need: NeedRenderData) { + protected renderStatic(transform: Transform, need: NeedRenderData) { const cell = this.cellSize; const frame = RenderItem.animatedFrame % 4; const { width } = this.block.blockData; @@ -1205,7 +1154,9 @@ export class Layer extends Container { ctx.save(); const { res: render } = need; - transformCanvas(this.staticMap, camera, false); + const [a, b, , c, d, , e, f] = transform.mat; + ctx.setTransform(1, 0, 0, 1, 0, 0); + ctx.transform(a, b, c, d, e, f); render.forEach(v => { const x = v % width; @@ -1277,17 +1228,16 @@ export class Layer extends Container { /** * 渲染移动/大怪物层 */ - protected renderMoving(camera: Camera) { + protected renderMoving(transform: Transform) { const frame = (RenderItem.animatedFrame % 4) + 1; const cell = this.cellSize; const halfCell = cell / 2; const { ctx } = this.movingMap; ctx.save(); - const mat = camera.mat; + const mat = transform.mat; const [a, b, , c, d, , e, f] = mat; ctx.setTransform(1, 0, 0, 1, 0, 0); - ctx.translate(core._PX_ / 2, core._PY_ / 2); ctx.transform(a, b, c, d, e, f); const max1 = Math.max(a, b, c, d) ** 2; const max2 = Math.max(core._PX_, core._PY_) * 2; diff --git a/src/core/render/preset/misc.ts b/src/core/render/preset/misc.ts index 20b02d7..630db02 100644 --- a/src/core/render/preset/misc.ts +++ b/src/core/render/preset/misc.ts @@ -1,3 +1,4 @@ +import { MotaOffscreenCanvas2D } from '@/core/fx/canvas2d'; import { Sprite } from '../sprite'; type CanvasStyle = string | CanvasGradient | CanvasPattern; @@ -12,6 +13,8 @@ export class Text extends Sprite { private length: number = 0; private descent: number = 0; + private static measureCanvas = new MotaOffscreenCanvas2D(); + constructor(text: string = '') { super(); @@ -39,11 +42,10 @@ export class Text extends Sprite { * 获取文字的长度 */ measure() { - this.canvas.ctx.save(); - this.canvas.ctx.textBaseline = 'bottom'; - this.canvas.ctx.font = this.font ?? ''; - const res = this.canvas.ctx.measureText(this.text); - this.canvas.ctx.restore(); + const ctx = Text.measureCanvas.ctx; + ctx.textBaseline = 'bottom'; + ctx.font = this.font ?? ''; + const res = ctx.measureText(this.text); return res; } @@ -53,8 +55,6 @@ export class Text extends Sprite { */ setText(text: string) { this.text = text; - this.writing = this.using; - this.using = void 0; this.calBox(); if (this.parent) this.update(this); } @@ -101,8 +101,6 @@ export class Image extends Sprite { constructor(image: SizedCanvasImageSource) { super(); this.image = image; - this.canvas.withGameScale(false); - this.canvas.setHD(false); this.size(image.width, image.height); this.renderFn = ({ canvas, ctx }) => { @@ -117,8 +115,6 @@ export class Image extends Sprite { setImage(image: SizedCanvasImageSource) { this.image = image; this.size(image.width, image.height); - this.writing = this.using; - this.using = void 0; this.update(this); } } diff --git a/src/core/render/render.ts b/src/core/render/render.ts index da03db0..6253dfe 100644 --- a/src/core/render/render.ts +++ b/src/core/render/render.ts @@ -1,8 +1,7 @@ import { Animation, hyper, sleep } from 'mutate-animate'; import { MotaCanvas2D, MotaOffscreenCanvas2D } from '../fx/canvas2d'; -import { Camera } from './camera'; import { Container } from './container'; -import { RenderItem, transformCanvas, withCacheRender } from './item'; +import { RenderItem, transformCanvas } from './item'; import { FloorLayer, Layer, LayerGroup } from './preset/layer'; import { LayerGroupFloorBinder } from './preset/floor'; import { FloorDamageExtends } from './preset/damage'; @@ -11,11 +10,6 @@ import { HeroRenderer } from './preset/hero'; export class MotaRenderer extends Container { static list: Set = new Set(); - canvas: MotaOffscreenCanvas2D; - camera: Camera; - - /** 摄像机缓存,如果是需要快速切换摄像机的场景,使用缓存可以大幅提升性能表现 */ - cameraCache: Map = new Map(); target: MotaCanvas2D; /** 这个渲染对象的id */ id: string; @@ -23,19 +17,14 @@ export class MotaRenderer extends Container { protected needUpdate: boolean = false; constructor(id: string = 'render-main') { - super(); + super('static', false); this.id = id; - this.canvas = new MotaOffscreenCanvas2D(); - this.camera = new Camera(); this.target = new MotaCanvas2D(id); - this.width = core._PX_; - this.height = core._PY_; + this.size(core._PX_, core._PY_); this.target.withGameScale(true); this.target.size(core._PX_, core._PY_); - this.canvas.withGameScale(true); - this.canvas.size(core._PX_, core._PY_); this.target.css(`z-index: 100`); MotaRenderer.list.add(this); @@ -47,62 +36,61 @@ export class MotaRenderer extends Container { * @param noCache 是否不使用缓存,当切换至的目标摄像机相比切走时发生了例如位置的变化时,一般需要设置为true, * 否则会使用上一次被切换走时的缓存 */ - useCamera(camera: Camera, noCache: boolean = false) { - const cache = MotaOffscreenCanvas2D.clone(this.canvas); - this.cameraCache.set(this.camera, cache); - this.camera = camera; - const nowCache = this.cameraCache.get(camera); - if (!nowCache || !noCache) this.render(); - else this.renderCache(nowCache); - } + // useCamera(camera: Camera, noCache: boolean = false) { + // const cache = MotaOffscreenCanvas2D.clone(this.canvas); + // this.cameraCache.set(this.camera, cache); + // this.camera = camera; + // const nowCache = this.cameraCache.get(camera); + // if (!nowCache || !noCache) this.render(); + // else this.renderCache(nowCache); + // } /** * 删除某个摄像机的画面缓存 * @param camera 要删除的缓存对应的摄像机 */ - freeCameraCache(camera: Camera) { - this.cameraCache.delete(camera); - } + // freeCameraCache(camera: Camera) { + // this.cameraCache.delete(camera); + // } /** * 渲染游戏画面 */ - render() { - // console.time(); - const { canvas, ctx } = this.target; - const camera = this.camera; - this.emit('beforeRender'); - ctx.clearRect(0, 0, canvas.width, canvas.height); - withCacheRender(this, canvas, ctx, camera, canvas => { - const { canvas: ca, ctx: ct, scale } = canvas; - this.sortedChildren.forEach(v => { - if (v.hidden) return; - if (v.type === 'absolute') { - ct.setTransform(scale, 0, 0, scale, 0, 0); - } else { - transformCanvas(canvas, camera, false); - } - ct.save(); - if (!v.antiAliasing) { - ctx.imageSmoothingEnabled = false; - ct.imageSmoothingEnabled = false; - } else { - ctx.imageSmoothingEnabled = true; - ct.imageSmoothingEnabled = true; - } - v.render(this.target, camera); - ct.restore(); - }); - }); - this.emit('afterRender'); - // console.timeEnd(); - } + // protected render(canvas: MotaOffscreenCanvas2D, transform: Transform) { + // console.time(); + // const { canvas, ctx } = this.target; + // const camera = this.camera; + // this.emit('beforeRender', camera); + // ctx.clearRect(0, 0, canvas.width, canvas.height); + // withCacheRender(this, canvas, ctx, camera, canvas => { + // const { canvas: ca, ctx: ct, scale } = canvas; + // this.sortedChildren.forEach(v => { + // if (v.hidden) return; + // if (v.type === 'absolute') { + // ct.setTransform(scale, 0, 0, scale, 0, 0); + // } else { + // transformCanvas(canvas, camera, false); + // } + // ct.save(); + // if (!v.antiAliasing) { + // ctx.imageSmoothingEnabled = false; + // ct.imageSmoothingEnabled = false; + // } else { + // ctx.imageSmoothingEnabled = true; + // ct.imageSmoothingEnabled = true; + // } + // v.renderContent(this.target, camera); + // ct.restore(); + // }); + // }); + // this.emit('afterRender', camera); + // console.timeEnd(); + // } update(item?: RenderItem) { if (this.needUpdate) return; this.needUpdate = true; this.requestRenderFrame(() => { - this.cache(this.using); this.needUpdate = false; this.refresh(item); }); @@ -110,20 +98,12 @@ export class MotaRenderer extends Container { protected refresh(item?: RenderItem): void { this.emit('beforeUpdate', item); - this.render(); + // console.time(); + this.render(this.target, this.transform); + // console.timeEnd(); this.emit('afterUpdate', item); } - /** - * 将缓存内容渲染至画面 - * @param cache 渲染缓存,是一个离屏Canvas2D对象 - */ - renderCache(cache: MotaOffscreenCanvas2D) { - const { canvas, ctx } = this.canvas; - ctx.clearRect(0, 0, canvas.width, canvas.width); - ctx.drawImage(cache.canvas, 0, 0); - } - /** * 添加至游戏画面 */ @@ -142,7 +122,7 @@ window.addEventListener('resize', () => { Mota.require('var', 'hook').once('reset', () => { const render = new MotaRenderer(); - const camera = render.camera; + const transform = render.transform; render.mount(); const layer = new LayerGroup(); @@ -174,8 +154,8 @@ Mota.require('var', 'hook').once('reset', () => { // } // ); - camera.move(240, 240); + transform.move(240, 240); render.update(); - console.log(layer); + console.log(render); }); diff --git a/src/core/render/sprite.ts b/src/core/render/sprite.ts index 89e2ec3..b16474e 100644 --- a/src/core/render/sprite.ts +++ b/src/core/render/sprite.ts @@ -1,76 +1,39 @@ -import { Camera } from './camera'; import { - ICanvasCachedRenderItem, + ERenderItemEvent, RenderFunction, RenderItem, - RenderItemPosition, - withCacheRender + RenderItemPosition } from './item'; import { MotaOffscreenCanvas2D } from '../fx/canvas2d'; +import { Transform } from './transform'; -export class Sprite extends RenderItem implements ICanvasCachedRenderItem { +export interface ESpriteEvent extends ERenderItemEvent {} + +export class Sprite extends RenderItem< + E | ESpriteEvent +> { renderFn: RenderFunction; - canvas: MotaOffscreenCanvas2D; - - private readonly enableCache: boolean; - /** * 创建一个精灵,可以自由在上面渲染内容 * @param type 渲染模式,absolute表示绝对位置,static表示跟随摄像机移动,只对顶层元素有效 * @param cache 是否启用缓存机制 */ constructor(type: RenderItemPosition = 'static', cache: boolean = true) { - super(); + super(cache); this.type = type; - this.enableCache = cache; this.renderFn = () => {}; - this.canvas = new MotaOffscreenCanvas2D(); - this.canvas.withGameScale(true); } - render(canvas: MotaOffscreenCanvas2D, camera: Camera): void { - this.emit('beforeRender'); - if (this.needUpdate) { - this.cache(this.using); - this.needUpdate = false; - } - if (this.enableCache) { - withCacheRender(this, canvas.canvas, canvas.ctx, camera, canvas => { - this.renderFn(canvas, camera); - }); - } else { - this.renderFn(canvas, camera); - } - this.writing = void 0; - this.emit('afterRender'); - } - - size(width: number, height: number) { - this.width = width; - this.height = height; - this.canvas.size(width, height); - this.update(this); - } - - pos(x: number, y: number) { - this.x = x; - this.y = y; + protected render( + canvas: MotaOffscreenCanvas2D, + transform: Transform + ): void { + this.renderFn(canvas, transform); } setRenderFn(fn: RenderFunction) { this.renderFn = fn; - } - - setHD(hd: boolean): void { - this.highResolution = hd; - this.canvas.setHD(hd); - this.update(this); - } - - setAntiAliasing(anti: boolean): void { - this.antiAliasing = anti; - this.canvas.setAntiAliasing(anti); this.update(this); } } diff --git a/src/core/render/camera.ts b/src/core/render/transform.ts similarity index 66% rename from src/core/render/camera.ts rename to src/core/render/transform.ts index 7eb8414..7e7cbd9 100644 --- a/src/core/render/camera.ts +++ b/src/core/render/transform.ts @@ -1,9 +1,6 @@ -import { ReadonlyMat3, ReadonlyVec3, mat3, vec2, vec3 } from 'gl-matrix'; -import { EventEmitter } from '../common/eventEmitter'; +import { mat3, ReadonlyMat3, ReadonlyVec3, vec2, vec3 } from 'gl-matrix'; -interface CameraEvent {} - -export class Camera extends EventEmitter { +export class Transform { mat: mat3 = mat3.create(); x: number = 0; @@ -12,10 +9,11 @@ export class Camera extends EventEmitter { scaleY: number = 1; rad: number = 0; - private saveStack: number[][] = []; + /** 有没有对这个Transform进行过修改,用于优化常规表现 */ + private modified: boolean = false; /** - * 重设摄像机的所有参数 + * 重设所有参数 */ reset() { mat3.identity(this.mat); @@ -24,28 +22,31 @@ export class Camera extends EventEmitter { this.scaleX = 1; this.scaleY = 1; this.rad = 0; + this.modified = false; } /** - * 修改摄像机的缩放,叠加关系 + * 修改缩放,叠加关系 */ scale(x: number, y: number = x) { mat3.scale(this.mat, this.mat, [x, y]); this.scaleX *= x; this.scaleY *= y; + this.modified = true; } /** - * 移动摄像机,叠加关系 + * 移动,叠加关系 */ move(x: number, y: number) { mat3.translate(this.mat, this.mat, [-x, -y]); this.x += x; this.y += y; + this.modified = true; } /** - * 旋转摄像机,叠加关系 + * 旋转,叠加关系 */ rotate(rad: number) { mat3.rotate(this.mat, this.mat, rad); @@ -54,36 +55,40 @@ export class Camera extends EventEmitter { const n = Math.floor(this.rad / Math.PI / 2); this.rad -= n * Math.PI * 2; } + this.modified = true; } /** - * 设置摄像机的缩放,非叠加关系 + * 设置缩放,非叠加关系 */ setScale(x: number, y: number = x) { mat3.scale(this.mat, this.mat, [x / this.scaleX, y / this.scaleY]); this.scaleX = x; this.scaleY = y; + this.modified = true; } /** - * 设置摄像机的位置,非叠加关系 + * 设置位置,非叠加关系 */ setTranslate(x: number, y: number) { mat3.translate(this.mat, this.mat, [this.x - x, this.y - y]); this.x = x; this.y = y; + this.modified = true; } /** - * 设置摄像机的旋转,非叠加关系 + * 设置旋转,非叠加关系 */ setRotate(rad: number) { mat3.rotate(this.mat, this.mat, rad - this.rad); this.rad = rad; + this.modified = true; } /** - * 设置摄像机的变换矩阵,叠加模式 + * 设置变换矩阵,叠加模式 * @param a 水平缩放 * @param b 垂直倾斜 * @param c 水平倾斜 @@ -108,7 +113,7 @@ export class Camera extends EventEmitter { } /** - * 设置摄像机的变换矩阵,非叠加模式 + * 设置变换矩阵,非叠加模式 * @param a 水平缩放 * @param b 垂直倾斜 * @param c 水平倾斜 @@ -140,46 +145,62 @@ export class Camera extends EventEmitter { this.scaleX = scaleX; this.scaleY = scaleY; this.rad = rad; + if (x === 0 && y === 0 && scaleX === 1 && scaleY === 1 && rad === 0) { + this.modified = false; + } else { + this.modified = true; + } } /** - * 保存当前摄像机状态 + * 与一个矩阵相乘,返回其计算结果(不改变原矩阵) + * @param transform 变换矩阵 */ - save() { - this.saveStack.push(Array.from(this.mat)); + multiply(transform: Transform): Transform { + if (this.modified) { + const res = new Transform(); + const mat = mat3.clone(this.mat); + mat3.multiply(mat, mat, transform.mat); + res.mat = mat; + return res; + } else { + return transform.clone(); + } } /** - * 回退当前摄像机状态 + * 复制这个变换矩阵 */ - restore() { - const data = this.saveStack.pop(); - if (!data) return; - const [a, b, c, d, e, f, g, h, i] = data; - this.mat = mat3.fromValues(a, b, c, d, e, f, g, h, i); + clone() { + const transform = new Transform(); + transform.mat = mat3.clone(this.mat); + return transform; } /** * 根据摄像机的信息,将一个点转换为计算后的位置 - * @param camera 摄像机 + * @param transform 摄像机 * @param x 横坐标 * @param y 纵坐标 */ - static transformed(camera: Camera, x: number, y: number) { - return multiplyVec3(camera.mat, [x, y, 1]); + static transformed(transform: Transform, x: number, y: number) { + return multiplyVec3(transform.mat, [x, y, 1]); } /** * 根据摄像机的信息,将一个计算后的位置逆转换为原位置 - * @param camera 摄像机 + * @param transform 摄像机 * @param x 横坐标 * @param y 纵坐标 */ - static untransformed(camera: Camera, x: number, y: number) { + static untransformed(transform: Transform, x: number, y: number) { const invert = mat3.create(); - mat3.invert(invert, camera.mat); + mat3.invert(invert, transform.mat); return multiplyVec3(invert, [x, y, 1]); } + + /** 单位矩阵 */ + static readonly identity = new Transform(); } function multiplyVec3(mat: ReadonlyMat3, vec: ReadonlyVec3) { diff --git a/src/game/index.ts b/src/game/index.ts index 1326535..2715dd2 100644 --- a/src/game/index.ts +++ b/src/game/index.ts @@ -10,6 +10,7 @@ import * as hero from './state/hero'; import * as miscMechanism from './mechanism/misc'; import * as study from './mechanism/study'; import { registerPresetState } from './state/preset'; +import { ItemState } from './state/item'; // ----- 类注册 Mota.register('class', 'DamageEnemy', damage.DamageEnemy); @@ -32,6 +33,9 @@ Mota.register('module', 'Mechanism', { BluePalace: miscMechanism.BluePalace, Study: study }); +Mota.register('module', 'State', { + ItemState +}); main.loading = loading; diff --git a/src/game/system.ts b/src/game/system.ts index 9261b0a..f2b206c 100644 --- a/src/game/system.ts +++ b/src/game/system.ts @@ -35,6 +35,7 @@ import type { Camera } from '@/core/render/camera'; import type { Image, Text } from '@/core/render/preset/misc'; import type { RenderItem } from '@/core/render/item'; import type { RenderAdapter } from '@/core/render/adapter'; +import type { ItemState } from './state/item'; interface ClassInterface { // 渲染进程与游戏进程通用 @@ -115,6 +116,9 @@ interface ModuleInterface { RenderItem: typeof RenderItem; RenderAdapter: typeof RenderAdapter; }; + State: { + ItemState: typeof ItemState; + }; } interface SystemInterfaceMap { diff --git a/src/plugin/game/fallback.ts b/src/plugin/game/fallback.ts index eda195b..b362601 100644 --- a/src/plugin/game/fallback.ts +++ b/src/plugin/game/fallback.ts @@ -261,8 +261,6 @@ export function init() { core.autosave(); } - console.trace(); - moveDir = direction; stepDir = direction; await readyMove();