mirror of
https://github.com/unanmed/HumanBreak.git
synced 2025-01-19 12:49:25 +08:00
fix: 模型变换
This commit is contained in:
parent
4835b0b367
commit
d7dcbe9d04
@ -6,13 +6,15 @@ export class Container extends RenderItem implements IRenderChildable {
|
||||
children: RenderItem[] = [];
|
||||
sortedChildren: RenderItem[] = [];
|
||||
|
||||
private needSort: boolean = false;
|
||||
|
||||
/**
|
||||
* 创建一个容器,容器中可以包含其他渲染对象
|
||||
* @param type 渲染模式,absolute表示绝对位置,static表示跟随摄像机移动
|
||||
* @param cache 是否启用缓存机制
|
||||
*/
|
||||
constructor(type: RenderItemPosition = 'static', cache: boolean = true) {
|
||||
super(cache);
|
||||
super(type, cache);
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
@ -21,14 +23,11 @@ export class Container extends RenderItem implements IRenderChildable {
|
||||
transform: Transform
|
||||
): void {
|
||||
const { ctx } = canvas;
|
||||
// console.log(ctx.getTransform());
|
||||
|
||||
this.sortedChildren.forEach(v => {
|
||||
if (v.hidden) return;
|
||||
ctx.save();
|
||||
if (v.antiAliasing) {
|
||||
ctx.imageSmoothingEnabled = true;
|
||||
} else {
|
||||
ctx.imageSmoothingEnabled = false;
|
||||
}
|
||||
v.renderContent(canvas, transform);
|
||||
ctx.restore();
|
||||
});
|
||||
@ -41,7 +40,13 @@ export class Container extends RenderItem implements IRenderChildable {
|
||||
appendChild(...children: RenderItem<any>[]) {
|
||||
children.forEach(v => (v.parent = this));
|
||||
this.children.push(...children);
|
||||
this.sortChildren();
|
||||
if (!this.needSort) {
|
||||
this.needSort = true;
|
||||
this.requestBeforeFrame(() => {
|
||||
this.needSort = false;
|
||||
this.sortChildren();
|
||||
});
|
||||
}
|
||||
this.update(this);
|
||||
}
|
||||
|
||||
|
@ -178,10 +178,11 @@ export abstract class RenderItem<E extends ERenderItemEvent = ERenderItemEvent>
|
||||
/** 是否启用缓存机制 */
|
||||
readonly enableCache: boolean = true;
|
||||
|
||||
constructor(enableCache: boolean = true) {
|
||||
constructor(type: RenderItemPosition, enableCache: boolean = true) {
|
||||
super();
|
||||
|
||||
this.enableCache = enableCache;
|
||||
this.type = type;
|
||||
this.cache.withGameScale(true);
|
||||
}
|
||||
|
||||
@ -218,27 +219,31 @@ export abstract class RenderItem<E extends ERenderItemEvent = ERenderItemEvent>
|
||||
if (this.hidden) return;
|
||||
this.emit('beforeRender', transform);
|
||||
this.needUpdate = false;
|
||||
const tran = transform.multiply(this.transform);
|
||||
const tran = this.transform;
|
||||
|
||||
const ax = -this.anchorX * this.width;
|
||||
const ay = -this.anchorY * this.height;
|
||||
|
||||
canvas.ctx.save();
|
||||
canvas.setAntiAliasing(this.antiAliasing);
|
||||
if (this.type === 'static') transformCanvas(canvas, tran);
|
||||
if (this.enableCache) {
|
||||
const { width, height, ctx } = this.cache;
|
||||
if (this.cacheDirty) {
|
||||
const cache = this.cache;
|
||||
this.render(cache, tran);
|
||||
this.cache = cache;
|
||||
const { canvas } = this.cache;
|
||||
ctx.clearRect(0, 0, canvas.width, canvas.height);
|
||||
ctx.save();
|
||||
this.render(this.cache, tran);
|
||||
ctx.restore();
|
||||
this.cacheDirty = false;
|
||||
}
|
||||
|
||||
canvas.ctx.save();
|
||||
if (this.type === 'static') transformCanvas(canvas, tran);
|
||||
canvas.ctx.drawImage(this.cache.canvas, ax, ay);
|
||||
canvas.ctx.restore();
|
||||
canvas.ctx.drawImage(this.cache.canvas, ax, ay, width, height);
|
||||
} else {
|
||||
canvas.ctx.save();
|
||||
if (this.type === 'static') transformCanvas(canvas, tran);
|
||||
canvas.ctx.translate(ax, ay);
|
||||
this.render(canvas, tran);
|
||||
canvas.ctx.restore();
|
||||
}
|
||||
canvas.ctx.restore();
|
||||
this.emit('afterRender', transform);
|
||||
}
|
||||
|
||||
@ -430,20 +435,10 @@ Mota.require('var', 'hook').once('reset', () => {
|
||||
|
||||
export function transformCanvas(
|
||||
canvas: MotaOffscreenCanvas2D,
|
||||
transform: Transform,
|
||||
clear: boolean = false
|
||||
transform: Transform
|
||||
) {
|
||||
const { canvas: ca, ctx, scale } = canvas;
|
||||
const { ctx } = canvas;
|
||||
const mat = transform.mat;
|
||||
const a = mat[0] * scale;
|
||||
const b = mat[1] * scale;
|
||||
const c = mat[3] * scale;
|
||||
const d = mat[4] * scale;
|
||||
const e = mat[6] * scale;
|
||||
const f = mat[7] * scale;
|
||||
ctx.setTransform(1, 0, 0, 1, 0, 0);
|
||||
if (clear) {
|
||||
ctx.clearRect(0, 0, ca.width, ca.height);
|
||||
}
|
||||
const [a, b, , c, d, , e, f] = mat;
|
||||
ctx.transform(a, b, c, d, e, f);
|
||||
}
|
||||
|
@ -62,6 +62,10 @@ export class FloorDamageExtends
|
||||
|
||||
private onUpdate = (floor: FloorIds) => {
|
||||
this.sprite.requestBeforeFrame(() => {
|
||||
if (!this.floorBinder.bindThisFloor) {
|
||||
ensureFloorDamage(floor);
|
||||
core.status.maps[floor].enemy.calRealAttribute();
|
||||
}
|
||||
this.update(floor);
|
||||
});
|
||||
};
|
||||
@ -71,6 +75,9 @@ export class FloorDamageExtends
|
||||
if (floor !== this.sprite.enemy?.floorId) return;
|
||||
this.sprite.updateEnemyOn(x, y);
|
||||
});
|
||||
if (!this.floorBinder.bindThisFloor) {
|
||||
this.sprite.enemy?.extract();
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
@ -169,10 +176,9 @@ export class Damage extends Sprite<EDamageEvent> {
|
||||
|
||||
this.setRenderFn((canvas, camera) => {
|
||||
const { ctx } = canvas;
|
||||
const { width, height } = canvas.canvas;
|
||||
const { width, height } = canvas;
|
||||
ctx.imageSmoothingEnabled = false;
|
||||
this.renderDamage(camera);
|
||||
ctx.setTransform(1, 0, 0, 1, 0, 0);
|
||||
ctx.drawImage(this.damageMap.canvas, 0, 0, width, height);
|
||||
});
|
||||
}
|
||||
@ -415,7 +421,8 @@ export class Damage extends Sprite<EDamageEvent> {
|
||||
// console.time('damage');
|
||||
const { ctx } = this.damageMap;
|
||||
ctx.save();
|
||||
transformCanvas(this.damageMap, transform, true);
|
||||
this.damageMap.clear();
|
||||
transformCanvas(this.damageMap, transform);
|
||||
|
||||
const { res: render } = this.calNeedRender(transform);
|
||||
const block = this.block;
|
||||
|
@ -70,6 +70,7 @@ export class LayerGroupFloorBinder
|
||||
bindThis() {
|
||||
this.floor = void 0;
|
||||
this.bindThisFloor = true;
|
||||
this.layerBinders.forEach(v => v.bindThis());
|
||||
this.updateBind();
|
||||
}
|
||||
|
||||
@ -80,6 +81,7 @@ export class LayerGroupFloorBinder
|
||||
bindFloor(floorId: FloorIds) {
|
||||
this.bindThisFloor = false;
|
||||
this.floor = floorId;
|
||||
this.layerBinders.forEach(v => v.bindFloor(floorId));
|
||||
this.updateBind();
|
||||
}
|
||||
|
||||
@ -103,7 +105,7 @@ export class LayerGroupFloorBinder
|
||||
v.updateBindData();
|
||||
});
|
||||
|
||||
const floor = this.bindThisFloor ? core.status.floorId : this.floor!;
|
||||
const floor = this.getFloor();
|
||||
this.emit('update', floor);
|
||||
}
|
||||
|
||||
@ -121,8 +123,6 @@ export class LayerGroupFloorBinder
|
||||
if (!ex) return;
|
||||
ex.setBlock(block, x, y);
|
||||
|
||||
console.log(block, x, y);
|
||||
|
||||
const floor = this.bindThisFloor ? core.status.floorId : this.floor!;
|
||||
this.emit('setBlock', x, y, floor, block);
|
||||
}
|
||||
@ -202,6 +202,10 @@ export class LayerFloorBinder implements ILayerRenderExtends {
|
||||
this.updateBind();
|
||||
}
|
||||
|
||||
getFloor() {
|
||||
return this.bindThisFloor ? core.status.floorId : this.floor!;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置这个拓展附属至的父拓展(LayerGroupFloorBinder拓展)
|
||||
* @param parent 父拓展
|
||||
@ -239,7 +243,7 @@ export class LayerFloorBinder implements ILayerRenderExtends {
|
||||
* 立刻更新绑定数据,而非下一帧
|
||||
*/
|
||||
updateBindData() {
|
||||
const floor = this.bindThisFloor ? core.status.floorId : this.floor;
|
||||
const floor = this.getFloor();
|
||||
if (!floor) return;
|
||||
core.extractBlocks(floor);
|
||||
const map = core.status.maps[floor];
|
||||
@ -276,3 +280,13 @@ export class LayerFloorBinder implements ILayerRenderExtends {
|
||||
this.parent?.layerBinders.delete(this);
|
||||
}
|
||||
}
|
||||
|
||||
export class LayerOpenDoorAnimate implements ILayerRenderExtends {
|
||||
id: string = 'open-door-animate';
|
||||
|
||||
layer!: Layer;
|
||||
|
||||
awake(layer: Layer) {
|
||||
this.layer = layer;
|
||||
}
|
||||
}
|
||||
|
@ -668,11 +668,9 @@ export class Layer extends Container {
|
||||
this.appendChild(this.main);
|
||||
this.main.setRenderFn((canvas, transform) => {
|
||||
const { ctx } = canvas;
|
||||
const { width, height } = canvas.canvas;
|
||||
ctx.imageSmoothingEnabled = false;
|
||||
const { width, height } = canvas;
|
||||
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);
|
||||
ctx.drawImage(this.movingMap.canvas, 0, 0, width, height);
|
||||
@ -1096,6 +1094,7 @@ export class Layer extends Container {
|
||||
for (const ex of this.extend.values()) {
|
||||
ex.onBeforeRender?.(this, transform, need);
|
||||
}
|
||||
|
||||
this.renderBack(transform, need);
|
||||
this.renderStatic(transform, need);
|
||||
this.renderMoving(transform);
|
||||
@ -1118,8 +1117,7 @@ export class Layer extends Container {
|
||||
|
||||
const mat = transform.mat;
|
||||
const [a, b, , c, d, , e, f] = mat;
|
||||
ctx.setTransform(1, 0, 0, 1, 0, 0);
|
||||
ctx.transform(a, b, c, d, e, f);
|
||||
ctx.setTransform(a, b, c, d, e, f);
|
||||
|
||||
if (this.background !== 0) {
|
||||
// 画背景图
|
||||
@ -1153,8 +1151,7 @@ export class Layer extends Container {
|
||||
|
||||
const { res: render } = need;
|
||||
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);
|
||||
ctx.setTransform(a, b, c, d, e, f);
|
||||
|
||||
render.forEach(v => {
|
||||
const x = v % width;
|
||||
@ -1235,8 +1232,7 @@ export class Layer extends Container {
|
||||
ctx.save();
|
||||
const mat = transform.mat;
|
||||
const [a, b, , c, d, , e, f] = mat;
|
||||
ctx.setTransform(1, 0, 0, 1, 0, 0);
|
||||
ctx.transform(a, b, c, d, e, f);
|
||||
ctx.setTransform(a, b, c, d, e, f);
|
||||
const max1 = Math.max(a, b, c, d) ** 2;
|
||||
const max2 = Math.max(core._PX_, core._PY_) * 2;
|
||||
const r = (max1 * max2) ** 2;
|
||||
|
@ -17,7 +17,7 @@ export class Text extends Sprite {
|
||||
private static measureCanvas = new MotaOffscreenCanvas2D();
|
||||
|
||||
constructor(text: string = '') {
|
||||
super();
|
||||
super('static', false);
|
||||
|
||||
this.text = text;
|
||||
if (text.length > 0) this.calBox();
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { Animation, hyper, sleep } from 'mutate-animate';
|
||||
import { Animation, hyper, linear, sleep } from 'mutate-animate';
|
||||
import { MotaCanvas2D, MotaOffscreenCanvas2D } from '../fx/canvas2d';
|
||||
import { Container } from './container';
|
||||
import { RenderItem, transformCanvas } from './item';
|
||||
@ -6,6 +6,8 @@ import { FloorLayer, Layer, LayerGroup } from './preset/layer';
|
||||
import { LayerGroupFloorBinder } from './preset/floor';
|
||||
import { FloorDamageExtends } from './preset/damage';
|
||||
import { HeroRenderer } from './preset/hero';
|
||||
import { Transform } from './transform';
|
||||
import { Text } from './preset/misc';
|
||||
|
||||
export class MotaRenderer extends Container {
|
||||
static list: Set<MotaRenderer> = new Set();
|
||||
@ -27,66 +29,12 @@ export class MotaRenderer extends Container {
|
||||
this.target.size(core._PX_, core._PY_);
|
||||
this.target.css(`z-index: 100`);
|
||||
|
||||
this.setAnchor(0.5, 0.5);
|
||||
this.transform.move(240, 240);
|
||||
|
||||
MotaRenderer.list.add(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* 使用某个摄像机
|
||||
* @param camera 要使用的摄像机
|
||||
* @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);
|
||||
// }
|
||||
|
||||
/**
|
||||
* 删除某个摄像机的画面缓存
|
||||
* @param camera 要删除的缓存对应的摄像机
|
||||
*/
|
||||
// freeCameraCache(camera: Camera) {
|
||||
// this.cameraCache.delete(camera);
|
||||
// }
|
||||
|
||||
/**
|
||||
* 渲染游戏画面
|
||||
*/
|
||||
// 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;
|
||||
@ -99,7 +47,8 @@ export class MotaRenderer extends Container {
|
||||
protected refresh(item?: RenderItem): void {
|
||||
this.emit('beforeUpdate', item);
|
||||
// console.time();
|
||||
this.render(this.target, this.transform);
|
||||
this.target.clear();
|
||||
this.renderContent(this.target, Transform.identity);
|
||||
// console.timeEnd();
|
||||
this.emit('afterUpdate', item);
|
||||
}
|
||||
@ -143,19 +92,6 @@ Mota.require('var', 'hook').once('reset', () => {
|
||||
layer.requestAfterFrame(() => {
|
||||
hero.setImage(core.material.images.images['hero2.png']);
|
||||
});
|
||||
// hero.readyMove();
|
||||
// layer.delegateTicker(
|
||||
// () => {
|
||||
// hero.move('right');
|
||||
// },
|
||||
// 10000,
|
||||
// () => {
|
||||
// hero.endMove();
|
||||
// }
|
||||
// );
|
||||
|
||||
transform.move(240, 240);
|
||||
render.update();
|
||||
|
||||
console.log(render);
|
||||
});
|
||||
|
@ -20,7 +20,7 @@ export class Sprite<E extends ESpriteEvent = ESpriteEvent> extends RenderItem<
|
||||
* @param cache 是否启用缓存机制
|
||||
*/
|
||||
constructor(type: RenderItemPosition = 'static', cache: boolean = true) {
|
||||
super(cache);
|
||||
super(type, cache);
|
||||
this.type = type;
|
||||
this.renderFn = () => {};
|
||||
}
|
||||
|
@ -39,7 +39,7 @@ export class Transform {
|
||||
* 移动,叠加关系
|
||||
*/
|
||||
move(x: number, y: number) {
|
||||
mat3.translate(this.mat, this.mat, [-x, -y]);
|
||||
mat3.translate(this.mat, this.mat, [x, y]);
|
||||
this.x += x;
|
||||
this.y += y;
|
||||
this.modified = true;
|
||||
@ -72,7 +72,7 @@ export class Transform {
|
||||
* 设置位置,非叠加关系
|
||||
*/
|
||||
setTranslate(x: number, y: number) {
|
||||
mat3.translate(this.mat, this.mat, [this.x - x, this.y - y]);
|
||||
mat3.translate(this.mat, this.mat, [x - this.x, y - this.y]);
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.modified = true;
|
||||
|
Loading…
Reference in New Issue
Block a user