mirror of
https://github.com/unanmed/HumanBreak.git
synced 2025-10-29 10:22:59 +08:00
feat: scan animater & refactor: 动画输出类型
This commit is contained in:
parent
fc1c0b14d6
commit
77246b571a
@ -105,6 +105,7 @@
|
||||
"71": "Cannot start animate when animater not created on texture.",
|
||||
"72": "Frame count delivered to frame-based animater need to exactly divide texture's height.",
|
||||
"73": "Consistent size is needed when using WebGL2 composer.",
|
||||
"74": "Frame size not match texture's size, incomplete data will be skipped.",
|
||||
"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."
|
||||
}
|
||||
|
||||
@ -1,10 +1,5 @@
|
||||
import { logger } from '@motajs/common';
|
||||
import {
|
||||
IRect,
|
||||
ITexture,
|
||||
ITextureAnimater,
|
||||
ITextureListedRenderable
|
||||
} from './types';
|
||||
import { IRect, ITexture, ITextureAnimater, ITextureRenderable } from './types';
|
||||
|
||||
/**
|
||||
* 基于帧的动画控制器,创建时传入的参数代表帧数,生成动画时传入的参数自定义
|
||||
@ -41,31 +36,31 @@ export abstract class FrameBasedAnimater<T>
|
||||
return true;
|
||||
}
|
||||
|
||||
abstract open(init: T): Generator<ITextureListedRenderable> | null;
|
||||
abstract open(init: T): Generator<ITextureRenderable> | null;
|
||||
|
||||
abstract cycled(init: T): Generator<ITextureListedRenderable> | null;
|
||||
abstract cycled(init: T): Generator<ITextureRenderable> | null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 行动画控制器,将贴图按照从上到下的顺序依次组成帧动画,创建时传入的参数代表帧数
|
||||
*/
|
||||
export class TextureRowAnimater extends FrameBasedAnimater<void> {
|
||||
*open(): Generator<ITextureListedRenderable> | null {
|
||||
*open(): Generator<ITextureRenderable> | null {
|
||||
if (!this.check()) return null;
|
||||
const renderable = this.texture!.static();
|
||||
const { x: ox, y: oy } = renderable.rect;
|
||||
const { width: w, height } = this.texture!;
|
||||
const h = height / this.frames;
|
||||
for (let i = 0; i < this.frames; i++) {
|
||||
const renderable: ITextureListedRenderable = {
|
||||
const renderable: ITextureRenderable = {
|
||||
source: this.texture!.source,
|
||||
rect: [{ x: ox, y: i * h + oy, w, h }]
|
||||
rect: { x: ox, y: i * h + oy, w, h }
|
||||
};
|
||||
yield renderable;
|
||||
}
|
||||
}
|
||||
|
||||
*cycled(): Generator<ITextureListedRenderable> | null {
|
||||
*cycled(): Generator<ITextureRenderable> | null {
|
||||
if (!this.check()) return null;
|
||||
const renderable = this.texture!.static();
|
||||
const { x: ox, y: oy } = renderable.rect;
|
||||
@ -74,9 +69,9 @@ export class TextureRowAnimater extends FrameBasedAnimater<void> {
|
||||
let i = 0;
|
||||
while (true) {
|
||||
if (i === this.frames) i = 0;
|
||||
const renderable: ITextureListedRenderable = {
|
||||
const renderable: ITextureRenderable = {
|
||||
source: this.texture!.source,
|
||||
rect: [{ x: ox, y: i * h + oy, w, h }]
|
||||
rect: { x: ox, y: i * h + oy, w, h }
|
||||
};
|
||||
yield renderable;
|
||||
}
|
||||
@ -87,22 +82,22 @@ export class TextureRowAnimater extends FrameBasedAnimater<void> {
|
||||
* 列动画控制器,将贴图按照从左到右的顺序依次组成帧动画,创建时传入的参数代表帧数
|
||||
*/
|
||||
export class TextureColumnAnimater extends FrameBasedAnimater<void> {
|
||||
*open(): Generator<ITextureListedRenderable> | null {
|
||||
*open(): Generator<ITextureRenderable> | null {
|
||||
if (!this.check()) return null;
|
||||
const renderable = this.texture!.static();
|
||||
const { x: ox, y: oy } = renderable.rect;
|
||||
const { width, height: h } = this.texture!;
|
||||
const w = width / this.frames;
|
||||
for (let i = 0; i < this.frames; i++) {
|
||||
const renderable: ITextureListedRenderable = {
|
||||
const renderable: ITextureRenderable = {
|
||||
source: this.texture!.source,
|
||||
rect: [{ x: i * width + ox, y: oy, w, h }]
|
||||
rect: { x: i * width + ox, y: oy, w, h }
|
||||
};
|
||||
yield renderable;
|
||||
}
|
||||
}
|
||||
|
||||
*cycled(): Generator<ITextureListedRenderable> | null {
|
||||
*cycled(): Generator<ITextureRenderable> | null {
|
||||
if (!this.check()) return null;
|
||||
const renderable = this.texture!.static();
|
||||
const { x: ox, y: oy } = renderable.rect;
|
||||
@ -111,15 +106,92 @@ export class TextureColumnAnimater extends FrameBasedAnimater<void> {
|
||||
let i = 0;
|
||||
while (true) {
|
||||
if (i === this.frames) i = 0;
|
||||
const renderable: ITextureListedRenderable = {
|
||||
const renderable: ITextureRenderable = {
|
||||
source: this.texture!.source,
|
||||
rect: [{ x: i * w + ox, y: oy, w, h }]
|
||||
rect: { x: i * w + ox, y: oy, w, h }
|
||||
};
|
||||
yield renderable;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export interface IScanAnimaterCreate {
|
||||
/** 每帧的宽度 */
|
||||
readonly width: number;
|
||||
/** 每帧的高度 */
|
||||
readonly height: number;
|
||||
/** 总帧数 */
|
||||
readonly frames: number;
|
||||
}
|
||||
|
||||
/**
|
||||
* 扫描动画控制器,会按照先从左到右,再从上到下的顺序依次输出,可以用于动画精灵图等
|
||||
*/
|
||||
export class TextureScanAnimater
|
||||
implements ITextureAnimater<IScanAnimaterCreate, void>
|
||||
{
|
||||
texture: ITexture<IScanAnimaterCreate, void> | null = null;
|
||||
|
||||
private width: number = 0;
|
||||
private height: number = 0;
|
||||
|
||||
private frames: number = 0;
|
||||
private frameX: number = 0;
|
||||
private frameY: number = 0;
|
||||
|
||||
create(texture: ITexture, data: IScanAnimaterCreate): void {
|
||||
if (this.texture) {
|
||||
logger.warn(70);
|
||||
return;
|
||||
}
|
||||
this.texture = texture;
|
||||
|
||||
this.width = data.width;
|
||||
this.height = data.height;
|
||||
this.frames = data.frames;
|
||||
|
||||
// 如果尺寸不匹配
|
||||
if (
|
||||
texture.width % data.width !== 0 ||
|
||||
texture.height % data.height !== 0
|
||||
) {
|
||||
logger.warn(74);
|
||||
}
|
||||
|
||||
const frameX = Math.floor(texture.width / data.width);
|
||||
const frameY = Math.floor(texture.height / data.height);
|
||||
const possibleFrames = frameX * frameY;
|
||||
|
||||
// 如果传入的帧数超出了可能的帧数上限
|
||||
if (this.frames > possibleFrames) {
|
||||
this.frames = possibleFrames;
|
||||
}
|
||||
}
|
||||
|
||||
*open(): Generator<ITextureRenderable, void> | null {
|
||||
const texture = this.texture;
|
||||
if (!texture) return null;
|
||||
|
||||
const w = this.width;
|
||||
const h = this.height;
|
||||
|
||||
for (let y = 0; y < this.frameY; y++) {
|
||||
for (let x = 0; x < this.frameX; x++) {
|
||||
const rect: IRect = { x: x * w, y: y * h, w, h };
|
||||
const data: ITextureRenderable = {
|
||||
source: texture.source,
|
||||
rect
|
||||
};
|
||||
yield data;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
cycled(): Generator<ITextureRenderable, void> | null {
|
||||
throw new Error('Method not implemented.');
|
||||
}
|
||||
}
|
||||
|
||||
export interface IAnimaterTranslatedInit<T> {
|
||||
/** 以此矩形作为参考矩形 */
|
||||
readonly rect: Readonly<IRect>;
|
||||
@ -141,11 +213,15 @@ export class TextureAnimaterTranslated<T> implements AdderImplements<T> {
|
||||
texture: AdderTexture<T> | null = null;
|
||||
|
||||
create(texture: ITexture): void {
|
||||
if (this.texture) {
|
||||
logger.warn(70);
|
||||
return;
|
||||
}
|
||||
this.texture = texture;
|
||||
}
|
||||
|
||||
*output(
|
||||
ani: Generator<ITextureListedRenderable>,
|
||||
ani: Generator<ITextureRenderable>,
|
||||
origin: Readonly<IRect>,
|
||||
rect: Readonly<IRect>
|
||||
) {
|
||||
@ -157,13 +233,11 @@ export class TextureAnimaterTranslated<T> implements AdderImplements<T> {
|
||||
const next = ani.next();
|
||||
if (next.done) break;
|
||||
const renderable = next.value;
|
||||
const list: IRect[] = [];
|
||||
renderable.rect.forEach(({ x, y, w, h }) => {
|
||||
list.push({ x: x - ox + nx, y: y - oy + ny, w, h });
|
||||
});
|
||||
const res: ITextureListedRenderable = {
|
||||
const { x, y, w, h } = renderable.rect;
|
||||
const translated: IRect = { x: x - ox + nx, y: y - oy + ny, w, h };
|
||||
const res: ITextureRenderable = {
|
||||
source,
|
||||
rect: list
|
||||
rect: translated
|
||||
};
|
||||
yield res;
|
||||
}
|
||||
@ -171,7 +245,7 @@ export class TextureAnimaterTranslated<T> implements AdderImplements<T> {
|
||||
|
||||
open(
|
||||
init: IAnimaterTranslatedInit<T>
|
||||
): Generator<ITextureListedRenderable> | null {
|
||||
): Generator<ITextureRenderable> | null {
|
||||
const ani = init.texture.dynamic(init.data);
|
||||
const origin = init.texture.static().rect;
|
||||
if (!ani || !origin) return null;
|
||||
@ -180,7 +254,7 @@ export class TextureAnimaterTranslated<T> implements AdderImplements<T> {
|
||||
|
||||
cycled(
|
||||
init: IAnimaterTranslatedInit<T>
|
||||
): Generator<ITextureListedRenderable> | null {
|
||||
): Generator<ITextureRenderable> | null {
|
||||
const ani = init.texture.cycled(init.data);
|
||||
const origin = init.texture.static().rect;
|
||||
if (!ani || !origin) return null;
|
||||
|
||||
@ -55,7 +55,8 @@ interface GridNeededSize {
|
||||
}
|
||||
|
||||
/**
|
||||
* 网格组合器,将等大小的贴图组合成图集,要求每个贴图的尺寸一致
|
||||
* 网格组合器,将等大小的贴图组合成图集,要求每个贴图的尺寸一致。
|
||||
* 组合时按照先从左到右,再从上到下的顺序组合。
|
||||
*/
|
||||
export class TextureGridComposer<T>
|
||||
implements TranslatedComposer<IGridComposerData, T>
|
||||
|
||||
@ -2,8 +2,7 @@ import { logger } from '@motajs/common';
|
||||
import {
|
||||
ITexture,
|
||||
ITextureAnimater,
|
||||
ITextureListedRenderable,
|
||||
ITextureSingleRenderable,
|
||||
ITextureRenderable,
|
||||
ITextureSplitter,
|
||||
SizedCanvasImageSource
|
||||
} from './types';
|
||||
@ -63,20 +62,20 @@ export class Texture<T = unknown, A = unknown> implements ITexture<T, A> {
|
||||
animater.create(this, data);
|
||||
}
|
||||
|
||||
static(): ITextureSingleRenderable {
|
||||
const renderable: ITextureSingleRenderable = {
|
||||
static(): ITextureRenderable {
|
||||
const renderable: ITextureRenderable = {
|
||||
source: this.source,
|
||||
rect: { x: this.cx, y: this.cy, w: this.width, h: this.height }
|
||||
};
|
||||
return renderable;
|
||||
}
|
||||
|
||||
dynamic(data: A): Generator<ITextureListedRenderable> | null {
|
||||
dynamic(data: A): Generator<ITextureRenderable> | null {
|
||||
if (!this.animater) return null;
|
||||
return this.animater.open(data);
|
||||
}
|
||||
|
||||
cycled(data: A): Generator<ITextureListedRenderable> | null {
|
||||
cycled(data: A): Generator<ITextureRenderable> | null {
|
||||
if (!this.animater) return null;
|
||||
return this.animater.cycled(data);
|
||||
}
|
||||
|
||||
@ -12,20 +12,13 @@ export interface IRect {
|
||||
h: number;
|
||||
}
|
||||
|
||||
export interface ITextureSingleRenderable {
|
||||
export interface ITextureRenderable {
|
||||
/** 可渲染贴图对象的图像源 */
|
||||
readonly source: SizedCanvasImageSource;
|
||||
/** 贴图裁剪区域 */
|
||||
readonly rect: Readonly<IRect>;
|
||||
}
|
||||
|
||||
export interface ITextureListedRenderable {
|
||||
/** 可渲染贴图对象的图像源 */
|
||||
readonly source: SizedCanvasImageSource;
|
||||
/** 贴图裁剪区域 */
|
||||
readonly rect: Readonly<IRect>[];
|
||||
}
|
||||
|
||||
export interface ITextureComposedData<T = unknown, A = unknown> {
|
||||
/** 这个纹理图集的贴图对象 */
|
||||
readonly texture: ITexture<T, A>;
|
||||
@ -69,13 +62,13 @@ export interface ITextureAnimater<T, I> {
|
||||
* 开始动画序列
|
||||
* @param init 动画初始化参数
|
||||
*/
|
||||
open(init: I): Generator<ITextureListedRenderable, void> | null;
|
||||
open(init: I): Generator<ITextureRenderable, void> | null;
|
||||
|
||||
/**
|
||||
* 开始循环动画序列
|
||||
* @param init 动画初始化参数
|
||||
*/
|
||||
cycled(init: I): Generator<ITextureListedRenderable, void> | null;
|
||||
cycled(init: I): Generator<ITextureRenderable, void> | null;
|
||||
}
|
||||
|
||||
export interface ITexture<T = unknown, A = unknown> {
|
||||
@ -111,19 +104,19 @@ export interface ITexture<T = unknown, A = unknown> {
|
||||
/**
|
||||
* 获取整张图的可渲染对象
|
||||
*/
|
||||
static(): ITextureSingleRenderable;
|
||||
static(): ITextureRenderable;
|
||||
|
||||
/**
|
||||
* 获取一系列动画可渲染对象,不循环,按帧数依次排列
|
||||
* @param data 传递给动画控制器的初始化参数
|
||||
*/
|
||||
dynamic(data: A): Generator<ITextureListedRenderable, void> | null;
|
||||
dynamic(data: A): Generator<ITextureRenderable, void> | null;
|
||||
|
||||
/**
|
||||
* 获取无限循环的动画可渲染对象
|
||||
* @param data 传递给动画控制器的初始化参数
|
||||
*/
|
||||
cycled(data: A): Generator<ITextureListedRenderable, void> | null;
|
||||
cycled(data: A): Generator<ITextureRenderable, void> | null;
|
||||
|
||||
/**
|
||||
* 释放此贴图的资源,将不能再被使用
|
||||
|
||||
Loading…
Reference in New Issue
Block a user