feat: setup project

This commit is contained in:
2026-09-05 15:27:53 +05:00
parent ae2a7e1ce9
commit c79681dc59
43 changed files with 2194 additions and 14 deletions
+58
View File
@@ -0,0 +1,58 @@
import { Container, Graphics, Text } from 'pixi.js';
import type { AvatarState } from '@idle/shared';
/**
* Заглушка M0: человечек из примитивов. С M1 сюда придут спрайты из паков —
* состав (тело + ник над головой) сохранится.
*/
export class AvatarView {
readonly container = new Container();
private readonly rig = new Container();
private readonly label: Text;
private targetX: number;
private targetY: number;
constructor(av: AvatarState) {
const shadow = new Graphics().ellipse(0, 0, 9, 3.5).fill({ color: 0x000000, alpha: 0.3 });
const body = new Graphics()
.roundRect(-7, -17, 14, 17, 5)
.fill(av.color)
.circle(0, -23, 7.5)
.fill(0xffe3c0);
this.label = new Text({
text: av.name,
style: {
fontFamily: 'monospace',
fontSize: 13,
fontWeight: 'bold',
fill: av.color,
stroke: { color: 0x10131a, width: 3 },
},
});
this.label.anchor.set(0.5, 1);
this.label.y = -36;
this.rig.addChild(shadow, body);
this.container.addChild(this.rig, this.label);
this.targetX = av.x;
this.targetY = av.y;
this.container.position.set(av.x, av.y);
this.apply(av);
}
apply(av: AvatarState): void {
this.targetX = av.x;
this.targetY = av.y;
this.rig.scale.x = av.face === 'left' ? -1 : 1;
if (this.label.text !== av.name) this.label.text = av.name;
if (this.label.style.fill !== av.color) this.label.style.fill = av.color;
}
/** Плавное дотягивание до последнего снапшота — сглаживает дискретность тиков. */
tick(dtMs: number): void {
const k = 1 - Math.exp(-dtMs / 120);
this.container.x += (this.targetX - this.container.x) * k;
this.container.y += (this.targetY - this.container.y) * k;
}
}