feat: fishing and cooking
This commit is contained in:
@@ -9,6 +9,7 @@ const BAR_FG = 0x9be870;
|
||||
const HANDLE = 0x8a6238;
|
||||
const STEEL = 0xb8c4d0;
|
||||
const RUSTY = 0x9a6a3f;
|
||||
const AURA = 0xffb347;
|
||||
|
||||
interface Chip {
|
||||
g: Graphics;
|
||||
@@ -27,14 +28,19 @@ function makeTool(tool: string): Graphics {
|
||||
g.poly([-1, -11, -8, -15, -8, -12, -1, -8]).fill(head);
|
||||
} else if (tool === 'hammer') {
|
||||
g.rect(-4, -15, 8, 4).fill(0x55606c);
|
||||
} else if (tool === 'spoon') {
|
||||
g.ellipse(0, -13, 2.5, 3.5).fill(RUSTY);
|
||||
} else if (tool === 'rod') {
|
||||
g.rect(-0.5, -20, 1.5, 20).fill(0x7d5a38);
|
||||
g.circle(0.25, -20, 1.5).fill(STEEL);
|
||||
}
|
||||
return g;
|
||||
}
|
||||
|
||||
/**
|
||||
* Аватар M2: процедурный человечек, в руках — текущий инструмент
|
||||
* (axe/pick тирами или молот у наковальни). Прогресс цикла клиент считает сам
|
||||
* из actionStart/actionDur.
|
||||
* Аватар M3: процедурный человечек с инструментом по действию (топор/кирка
|
||||
* тирами, молот, ложка, удочка), аурой баффа отдыха и прогресс-баром цикла.
|
||||
* Прогресс клиент считает сам из actionStart/actionDur.
|
||||
*/
|
||||
export class AvatarView {
|
||||
readonly container = new Container();
|
||||
@@ -43,6 +49,7 @@ export class AvatarView {
|
||||
private readonly legR: Graphics;
|
||||
private readonly toolHolder = new Container();
|
||||
private readonly tools = new Map<string, Graphics>();
|
||||
private readonly aura = new Graphics();
|
||||
private readonly label: Text;
|
||||
private readonly bar: Graphics;
|
||||
private chips: Chip[] = [];
|
||||
@@ -61,7 +68,7 @@ export class AvatarView {
|
||||
const body = new Graphics().roundRect(-7, -18, 14, 13, 4).fill(av.color);
|
||||
const head = new Graphics().circle(0, -23, 6.5).fill(SKIN);
|
||||
this.toolHolder.position.set(6, -14);
|
||||
for (const tool of ['axe_rusty', 'axe_iron', 'pick_rusty', 'pick_iron', 'hammer']) {
|
||||
for (const tool of ['axe_rusty', 'axe_iron', 'pick_rusty', 'pick_iron', 'hammer', 'spoon', 'rod']) {
|
||||
const g = makeTool(tool);
|
||||
g.visible = false;
|
||||
this.tools.set(tool, g);
|
||||
@@ -80,9 +87,11 @@ export class AvatarView {
|
||||
this.label.anchor.set(0.5, 1);
|
||||
this.label.y = -42;
|
||||
this.bar = new Graphics();
|
||||
this.aura.ellipse(0, 0, 15, 6.5).fill({ color: AURA, alpha: 0.3 });
|
||||
this.aura.visible = false;
|
||||
|
||||
this.rig.addChild(shadow, this.legL, this.legR, body, head, this.toolHolder);
|
||||
this.container.addChild(this.rig, this.bar, this.label);
|
||||
this.container.addChild(this.aura, this.rig, this.bar, this.label);
|
||||
|
||||
this.container.position.set(av.x, av.y);
|
||||
this.applyLabel(av);
|
||||
@@ -127,8 +136,13 @@ export class AvatarView {
|
||||
this.lastTool = av.tool;
|
||||
for (const [id, g] of this.tools) g.visible = id === av.tool;
|
||||
}
|
||||
const working = av.action === 'chop' || av.action === 'mine' || av.action === 'smith';
|
||||
const working =
|
||||
av.action === 'chop' || av.action === 'mine' || av.action === 'smith' || av.action === 'cook' || av.action === 'fish';
|
||||
this.toolHolder.visible = working && av.tool !== 'none';
|
||||
this.aura.visible = av.restStacks > 0;
|
||||
if (this.aura.visible) {
|
||||
this.aura.alpha = 0.5 + av.restStacks * 0.2 + Math.sin(now / 300) * 0.08;
|
||||
}
|
||||
|
||||
const t = now / 1000;
|
||||
if (av.moving) {
|
||||
@@ -136,7 +150,16 @@ export class AvatarView {
|
||||
this.legL.rotation = swing * 0.5;
|
||||
this.legR.rotation = -swing * 0.5;
|
||||
this.rig.y = -Math.abs(Math.cos(t * 12)) * 1.5;
|
||||
this.toolHolder.rotation = 0;
|
||||
this.bar.visible = false;
|
||||
} else if (av.action === 'rest') {
|
||||
// отдых: спокойное дыхание
|
||||
this.rig.y = Math.sin(t * 1.5) * 0.6;
|
||||
this.legL.rotation = 0;
|
||||
this.legR.rotation = 0;
|
||||
this.toolHolder.rotation = 0;
|
||||
this.bar.visible = false;
|
||||
this.lastChopPhase = 0;
|
||||
} else if (working && av.actionStart !== null && av.actionDur) {
|
||||
const p = ((((now - av.actionStart) / av.actionDur) % 1) + 1) % 1;
|
||||
const swing = Math.sin((Math.min(p, 0.35) / 0.35) * Math.PI);
|
||||
@@ -148,10 +171,11 @@ export class AvatarView {
|
||||
this.bar.clear();
|
||||
this.bar.roundRect(-12, -36, 24, 3.5, 1.5).fill({ color: BAR_BG, alpha: 0.6 });
|
||||
this.bar.roundRect(-12, -36, 24 * p, 3.5, 1.5).fill(BAR_FG);
|
||||
if (this.lastChopPhase < 0.33 && p >= 0.33) this.spawnChips();
|
||||
const chipsy = av.action === 'chop' || av.action === 'mine';
|
||||
if (chipsy && this.lastChopPhase < 0.33 && p >= 0.33) this.spawnChips();
|
||||
this.lastChopPhase = p < this.lastChopPhase ? 0 : p;
|
||||
} else {
|
||||
// отдых: лёгкое «дыхание»
|
||||
// отдых в сторону: лёгкое «дыхание»
|
||||
this.rig.y = Math.sin(t * 2) * 0.8;
|
||||
this.legL.rotation = 0;
|
||||
this.legR.rotation = 0;
|
||||
|
||||
Reference in New Issue
Block a user