From 5e54cc942418a6999f586f50b98afe96a816cea7 Mon Sep 17 00:00:00 2001 From: unanmed <1319491857@qq.com> Date: Tue, 20 Aug 2024 18:04:22 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E5=B8=A7=E5=8A=A8=E7=94=BB=20&=20fix:?= =?UTF-8?q?=20=E5=8B=87=E5=A3=AB=E7=A7=BB=E5=8A=A8?= 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/render/item.ts | 42 ++++++++++++++++++++++++++++---- src/core/render/preset/damage.ts | 19 +++++++++++---- src/core/render/preset/hero.ts | 7 ++++-- src/core/render/preset/layer.ts | 39 +++++++++++------------------ src/core/render/render.ts | 13 +++++++--- 7 files changed, 84 insertions(+), 42 deletions(-) diff --git a/src/core/fx/canvas2d.ts b/src/core/fx/canvas2d.ts index 33629f5..edbe320 100644 --- a/src/core/fx/canvas2d.ts +++ b/src/core/fx/canvas2d.ts @@ -25,6 +25,9 @@ export class MotaOffscreenCanvas2D extends EventEmitter<OffscreenCanvasEvent> { scale: number = 1; + /** 更新标识符,如果发生变化则说明画布被动清空 */ + symbol: number = 0; + constructor() { super(); @@ -248,6 +251,7 @@ window.addEventListener('resize', () => { MotaOffscreenCanvas2D.list.forEach(v => { if (v.autoScale) { v.size(v.width, v.height); + v.symbol++; v.emit('resize'); } }); diff --git a/src/core/index.ts b/src/core/index.ts index b4e1df4..ed8b265 100644 --- a/src/core/index.ts +++ b/src/core/index.ts @@ -62,7 +62,6 @@ import { Danmaku } from './main/custom/danmaku'; import * as Shadow from './fx/shadow'; import { MotaCanvas2D } from './fx/canvas2d'; import * as portal from './fx/portal'; -import { heroRender } from './render/hero'; import { MotaRenderer } from './render/render'; import { Container } from './render/container'; import { Sprite } from './render/sprite'; @@ -148,7 +147,6 @@ Mota.register('module', 'Effect', { Portal: portal }); Mota.register('module', 'Render', { - heroRender, texture, MotaRenderer, Container, diff --git a/src/core/render/item.ts b/src/core/render/item.ts index e4b48cd..acf92e0 100644 --- a/src/core/render/item.ts +++ b/src/core/render/item.ts @@ -1,5 +1,5 @@ import { isNil } from 'lodash-es'; -import { EventEmitter } from '../common/eventEmitter'; +import { EventEmitter } from 'eventemitter3'; import { MotaOffscreenCanvas2D } from '../fx/canvas2d'; import { Camera } from './camera'; import { Ticker, TickerFn } from 'mutate-animate'; @@ -379,11 +379,43 @@ RenderItem.ticker.add(() => { } }); -interface RenderEvent { - animateFrame: (frame: number, time: number) => void; +export interface IAnimateFrame { + updateFrameAnimate(frame: number, time: number): void; } -export const renderEmits = new EventEmitter<RenderEvent>(); +interface RenderEvent { + animateFrame: [frame: number, time: number]; +} + +class RenderEmits extends EventEmitter<RenderEvent> { + private framer: Set<IAnimateFrame> = new Set(); + + /** + * 添加一个可更新帧动画的对象 + */ + addFramer(framer: IAnimateFrame) { + this.framer.add(framer); + } + + /** + * 移除一个可更新帧动画的对象 + */ + removeFramer(framer: IAnimateFrame) { + this.framer.delete(framer); + } + + /** + * 更新所有帧动画 + * @param frame 帧数 + * @param time 帧动画时刻 + */ + emitAnimateFrame(frame: number, time: number) { + this.framer.forEach(v => v.updateFrameAnimate(frame, time)); + this.emit('animateFrame', frame, time); + } +} + +export const renderEmits = new RenderEmits(); Mota.require('var', 'hook').once('reset', () => { let lastTime = 0; @@ -392,7 +424,7 @@ Mota.require('var', 'hook').once('reset', () => { if (time - lastTime > core.values.animateSpeed) { RenderItem.animatedFrame++; lastTime = time; - renderEmits.emit('animateFrame', RenderItem.animatedFrame, time); + renderEmits.emitAnimateFrame(RenderItem.animatedFrame, time); } }); }); diff --git a/src/core/render/preset/damage.ts b/src/core/render/preset/damage.ts index 8e99e9c..5e0152a 100644 --- a/src/core/render/preset/damage.ts +++ b/src/core/render/preset/damage.ts @@ -104,11 +104,16 @@ interface DamageRenderable { strokeWidth?: number; } +interface DamageCache { + canvas: MotaOffscreenCanvas2D; + symbol: number; +} + export class Damage extends Sprite { mapWidth: number = 0; mapHeight: number = 0; - block: BlockCacher<HTMLCanvasElement>; + block: BlockCacher<DamageCache>; /** 键表示分块索引,值表示在这个分块上的渲染信息(当然实际渲染位置可以不在这个分块上) */ renderable: Map<number, Set<DamageRenderable>> = new Map(); @@ -404,13 +409,14 @@ export class Damage extends Sprite { // todo: 是否真的需要缓存 // 检查有没有缓存 const cache = block.cache.get(v * block.cacheDepth); - if (cache) { - ctx.drawImage(cache, px, py, size, size); + if (cache && cache.symbol === cache.canvas.symbol) { + ctx.drawImage(cache.canvas.canvas, px, py, size, size); return; } // 否则依次渲染并写入缓存 - const temp = new MotaOffscreenCanvas2D(); + const temp = cache?.canvas ?? new MotaOffscreenCanvas2D(); + temp.clear(); temp.setHD(true); temp.setAntiAliasing(true); temp.withGameScale(true); @@ -431,7 +437,10 @@ export class Damage extends Sprite { }); ctx.drawImage(temp.canvas, px, py, size, size); - block.cache.set(v, temp.canvas); + block.cache.set(v, { + canvas: temp, + symbol: temp.symbol + }); }); ctx.restore(); // console.timeEnd('damage'); diff --git a/src/core/render/preset/hero.ts b/src/core/render/preset/hero.ts index e3f386c..6337b0c 100644 --- a/src/core/render/preset/hero.ts +++ b/src/core/render/preset/hero.ts @@ -140,6 +140,7 @@ export class HeroRenderer } const progress = (time - this.lastStepTime) / this.speed; + const { x: dx, y: dy } = this.stepDelta; const { x, y } = core.status.hero.loc; if (progress >= 1) { @@ -184,8 +185,10 @@ export class HeroRenderer else { this.step(); return (this.moveDetached = new Promise<void>(resolve => { - this.moveDetached = void 0; - this.once('stepEnd', resolve); + this.once('stepEnd', () => { + this.moveDetached = void 0; + resolve(); + }); })); } } diff --git a/src/core/render/preset/layer.ts b/src/core/render/preset/layer.ts index 305d1c4..890a06d 100644 --- a/src/core/render/preset/layer.ts +++ b/src/core/render/preset/layer.ts @@ -3,7 +3,12 @@ import { Container } from '../container'; import { Sprite } from '../sprite'; import { Camera } from '../camera'; import { TimingFn } from 'mutate-animate'; -import { RenderItem, renderEmits, transformCanvas } from '../item'; +import { + IAnimateFrame, + renderEmits, + RenderItem, + transformCanvas +} from '../item'; import { logger } from '@/core/common/logger'; import { AutotileRenderable, RenderableData, texture } from '../cache'; import { glMatrix } from 'gl-matrix'; @@ -83,7 +88,7 @@ export interface ILayerGroupRenderExtends { export type FloorLayer = 'bg' | 'bg2' | 'event' | 'fg' | 'fg2'; -export class LayerGroup extends Container { +export class LayerGroup extends Container implements IAnimateFrame { /** 地图组列表 */ // static list: Set<LayerGroup> = new Set(); @@ -113,9 +118,7 @@ export class LayerGroup extends Container { this.releaseNeedRender(); }); - // this.usePreset('defaults'); - // LayerGroup.list.add(this); - // this.bindFloor(floor); + renderEmits.addFramer(this); } /** @@ -157,7 +160,6 @@ export class LayerGroup extends Container { this.layers.forEach(v => { v.block.setBlockSize(size); }); - // this.damage?.block.setBlockSize(size); } /** @@ -173,11 +175,8 @@ export class LayerGroup extends Container { */ emptyLayer() { this.removeChild(...this.layers.values()); - // if (this.damage) this.removeChild(this.damage); - // this.damage?.destroy(); this.layers.forEach(v => v.destroy()); this.layers.clear(); - // this.damage = void 0; for (const ex of this.extend.values()) { ex.onEmptyLayer?.(this); @@ -190,7 +189,6 @@ export class LayerGroup extends Container { */ addLayer(layer: FloorLayer) { const l = new Layer(); - // l.bindLayer(layer); l.layer = layer; if (l.layer) this.layers.set(l.layer, l); this.appendChild(l); @@ -293,7 +291,6 @@ export class LayerGroup extends Container { this.layers.forEach(v => { v.cache(v.using); }); - // this.damage?.cache(this.damage.using); this.update(this); for (const ex of this.extend.values()) { @@ -306,19 +303,10 @@ export class LayerGroup extends Container { ex.onDestroy?.(this); } super.destroy(); - // LayerGroup.list.delete(this); + renderEmits.removeFramer(this); } } -const hook = Mota.require('var', 'hook'); - -// todo: animate frame. -// renderEmits.on('animateFrame', () => { -// LayerGroup.list.forEach(v => { -// v.updateFrameAnimate(); -// }); -// }); - export function calNeedRenderOf( camera: Camera, cell: number, @@ -601,8 +589,8 @@ export interface ILayerRenderExtends { } interface LayerCacheItem { - // todo: 删掉这个属性 - canvas: HTMLCanvasElement; + symbol: number; + canvas: MotaOffscreenCanvas2D; } export interface LayerMovingRenderable extends RenderableData { @@ -1227,7 +1215,7 @@ export class Layer extends Container { const cache = this.block.cache.get(index); if (cache) { ctx.drawImage( - cache.canvas, + cache.canvas.canvas, sx * cell, sy * cell, blockSize * cell, @@ -1276,7 +1264,8 @@ export class Layer extends Container { blockSize * cell ); this.block.cache.set(index, { - canvas: temp.canvas + canvas: temp, + symbol: temp.symbol }); }); diff --git a/src/core/render/render.ts b/src/core/render/render.ts index 268616e..e527d5f 100644 --- a/src/core/render/render.ts +++ b/src/core/render/render.ts @@ -163,9 +163,16 @@ Mota.require('var', 'hook').once('reset', () => { layer.requestAfterFrame(() => { hero.setImage(core.material.images.images['hero2.png']); }); - layer.delegateTicker(() => { - hero.turn(); - }, 10000); + hero.readyMove(); + layer.delegateTicker( + () => { + hero.move('right'); + }, + 10000, + () => { + hero.endMove(); + } + ); camera.move(240, 240); render.update();