feat: 摄像机

This commit is contained in:
unanmed 2024-05-10 17:33:27 +08:00
parent 2f8fbd375c
commit 1e308540ac
6 changed files with 38 additions and 22 deletions

View File

@ -37,7 +37,7 @@ export class Camera extends EventEmitter<CameraEvent> {
*
*/
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;
}
@ -67,7 +67,7 @@ export class Camera extends EventEmitter<CameraEvent> {
*
*/
setTranslate(x: number, y: number) {
mat3.translate(this.mat, this.mat, [x - this.x, y - this.y]);
mat3.translate(this.mat, this.mat, [this.x - x, this.y - y]);
this.x = x;
this.y = y;
}

View File

@ -31,6 +31,7 @@ export class Container extends RenderItem implements ICanvasCachedRenderItem {
v.render(c.canvas, c.ctx, camera);
});
});
this.writing = void 0;
this.emit('afterUpdate', this);
}

View File

@ -151,8 +151,7 @@ export abstract class RenderItem
}
update(item?: RenderItem): void {
this.writing = this.using;
this.using = void 0;
this.cache(this.writing);
this.parent?.update(item);
}
}
@ -168,7 +167,7 @@ export function withCacheRender(
const ax = width * item.anchorX;
const ay = height * item.anchorY;
let write = item.writing;
if (!isNil(item.using)) {
if (!isNil(item.using) && isNil(item.writing)) {
const cache = item.cacheList.get(item.using);
if (cache) {
ctx.drawImage(
@ -189,12 +188,11 @@ export function withCacheRender(
const cache = item.cacheList.get(write);
if (cache) {
const { canvas, ctx } = cache;
ctx.drawImage(c, 0, 0);
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);
item.using = write;
}

View File

@ -102,10 +102,11 @@ export class Image extends Sprite {
super();
this.image = image;
this.canvas.withGameScale(false);
this.canvas.setHD(false);
this.size(image.width, image.height);
this.renderFn = ({ canvas, ctx }) => {
ctx.drawImage(this.image, 0, 0);
ctx.drawImage(this.image, 0, 0, canvas.width, canvas.height);
};
}

View File

@ -4,6 +4,7 @@ import { Camera } from './camera';
import { Container } from './container';
import { RenderItem, withCacheRender } from './item';
import { Image, Text } from './preset/misc';
import { Animation, hyper } from 'mutate-animate';
export class MotaRenderer extends Container {
canvas: MotaOffscreenCanvas2D;
@ -64,16 +65,18 @@ export class MotaRenderer extends Container {
const { canvas: ca, ctx: ct, scale } = canvas;
const mat = camera.mat;
const a = mat[0] * scale;
const b = mat[1];
const c = mat[3];
const b = mat[1] * scale;
const c = mat[3] * scale;
const d = mat[4] * scale;
const e = mat[6];
const f = mat[7];
const e = mat[6] * scale;
const f = mat[7] * scale;
this.sortedChildren.forEach(v => {
if (v.type === 'absolute') {
ct.setTransform(scale, 0, 0, scale, 0, 0);
ct.transform(scale, 0, 0, scale, 0, 0);
} else {
ct.setTransform(a, b, c, d, e, f);
ct.setTransform(1, 0, 0, 1, 0, 0);
ct.translate(ca.width / 2, ca.height / 2);
ct.transform(a, b, c, d, e, f);
}
v.render(ca, ct, camera);
});
@ -87,13 +90,11 @@ export class MotaRenderer extends Container {
if (this.needUpdate) return;
this.needUpdate = true;
requestAnimationFrame(() => {
this.writing = this.using;
this.using = void 0;
this.cache(this.writing);
this.needUpdate = false;
this.emit('beforeUpdate', item);
this.render();
this.emit('afterUpdate', item);
this.using = this.writing;
});
}
@ -123,12 +124,13 @@ Mota.require('var', 'hook').once('reset', () => {
const testText = new Text();
testText.setText('测试测试');
testText.pos(100, 100);
testText.pos(240, 240);
testText.setFont('32px normal');
testText.setStyle('#fff');
con.size(480, 480);
con.pos(-240, -240);
const testImage = new Image(core.material.images.images['arrow.png']);
testImage.pos(200, 200);
testImage.pos(240, 240);
con.appendChild([testText, testImage]);
@ -136,7 +138,20 @@ Mota.require('var', 'hook').once('reset', () => {
render.update(render);
setTimeout(() => {
testText.setFont('18px normal');
}, 2000);
const ani = new Animation();
ani.mode(hyper('sin', 'in-out'))
.time(10000)
.absolute()
.rotate(360)
.scale(0.7)
.move(100, 100);
ani.ticker.add(() => {
render.cache('@default');
camera.reset();
camera.move(ani.x, ani.y);
camera.scale(ani.size);
camera.rotate((ani.angle / 180) * Math.PI);
render.update(render);
});
setTimeout(() => ani.ticker.destroy(), 10000);
});

View File

@ -23,6 +23,7 @@ export class Sprite extends RenderItem {
withCacheRender(this, canvas, ctx, camera, canvas => {
this.renderFn(canvas, camera);
});
this.writing = void 0;
this.emit('afterUpdate', this);
}