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

View File

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

View File

@ -151,8 +151,7 @@ export abstract class RenderItem
} }
update(item?: RenderItem): void { update(item?: RenderItem): void {
this.writing = this.using; this.cache(this.writing);
this.using = void 0;
this.parent?.update(item); this.parent?.update(item);
} }
} }
@ -168,7 +167,7 @@ export function withCacheRender(
const ax = width * item.anchorX; const ax = width * item.anchorX;
const ay = height * item.anchorY; const ay = height * item.anchorY;
let write = item.writing; let write = item.writing;
if (!isNil(item.using)) { if (!isNil(item.using) && isNil(item.writing)) {
const cache = item.cacheList.get(item.using); const cache = item.cacheList.get(item.using);
if (cache) { if (cache) {
ctx.drawImage( ctx.drawImage(
@ -189,12 +188,11 @@ export function withCacheRender(
const cache = item.cacheList.get(write); const cache = item.cacheList.get(write);
if (cache) { if (cache) {
const { canvas, ctx } = cache; const { canvas, ctx } = cache;
ctx.drawImage(c, 0, 0); ctx.drawImage(c, 0, 0, canvas.width, canvas.height);
} else { } else {
item.cacheList.set(write, MotaOffscreenCanvas2D.clone(item.canvas)); item.cacheList.set(write, MotaOffscreenCanvas2D.clone(item.canvas));
} }
} }
ctx.drawImage(c, item.x - ax, item.y - ay, item.width, item.height); 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(); super();
this.image = image; this.image = image;
this.canvas.withGameScale(false); this.canvas.withGameScale(false);
this.canvas.setHD(false);
this.size(image.width, image.height); this.size(image.width, image.height);
this.renderFn = ({ canvas, ctx }) => { 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 { Container } from './container';
import { RenderItem, withCacheRender } from './item'; import { RenderItem, withCacheRender } from './item';
import { Image, Text } from './preset/misc'; import { Image, Text } from './preset/misc';
import { Animation, hyper } from 'mutate-animate';
export class MotaRenderer extends Container { export class MotaRenderer extends Container {
canvas: MotaOffscreenCanvas2D; canvas: MotaOffscreenCanvas2D;
@ -64,16 +65,18 @@ export class MotaRenderer extends Container {
const { canvas: ca, ctx: ct, scale } = canvas; const { canvas: ca, ctx: ct, scale } = canvas;
const mat = camera.mat; const mat = camera.mat;
const a = mat[0] * scale; const a = mat[0] * scale;
const b = mat[1]; const b = mat[1] * scale;
const c = mat[3]; const c = mat[3] * scale;
const d = mat[4] * scale; const d = mat[4] * scale;
const e = mat[6]; const e = mat[6] * scale;
const f = mat[7]; const f = mat[7] * scale;
this.sortedChildren.forEach(v => { this.sortedChildren.forEach(v => {
if (v.type === 'absolute') { if (v.type === 'absolute') {
ct.setTransform(scale, 0, 0, scale, 0, 0); ct.transform(scale, 0, 0, scale, 0, 0);
} else { } 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); v.render(ca, ct, camera);
}); });
@ -87,13 +90,11 @@ export class MotaRenderer extends Container {
if (this.needUpdate) return; if (this.needUpdate) return;
this.needUpdate = true; this.needUpdate = true;
requestAnimationFrame(() => { requestAnimationFrame(() => {
this.writing = this.using; this.cache(this.writing);
this.using = void 0;
this.needUpdate = false; this.needUpdate = false;
this.emit('beforeUpdate', item); this.emit('beforeUpdate', item);
this.render(); this.render();
this.emit('afterUpdate', item); this.emit('afterUpdate', item);
this.using = this.writing;
}); });
} }
@ -123,12 +124,13 @@ Mota.require('var', 'hook').once('reset', () => {
const testText = new Text(); const testText = new Text();
testText.setText('测试测试'); testText.setText('测试测试');
testText.pos(100, 100); testText.pos(240, 240);
testText.setFont('32px normal'); testText.setFont('32px normal');
testText.setStyle('#fff'); testText.setStyle('#fff');
con.size(480, 480); con.size(480, 480);
con.pos(-240, -240);
const testImage = new Image(core.material.images.images['arrow.png']); const testImage = new Image(core.material.images.images['arrow.png']);
testImage.pos(200, 200); testImage.pos(240, 240);
con.appendChild([testText, testImage]); con.appendChild([testText, testImage]);
@ -136,7 +138,20 @@ Mota.require('var', 'hook').once('reset', () => {
render.update(render); render.update(render);
setTimeout(() => { const ani = new Animation();
testText.setFont('18px normal'); ani.mode(hyper('sin', 'in-out'))
}, 2000); .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 => { withCacheRender(this, canvas, ctx, camera, canvas => {
this.renderFn(canvas, camera); this.renderFn(canvas, camera);
}); });
this.writing = void 0;
this.emit('afterUpdate', this); this.emit('afterUpdate', this);
} }