feat(rosto): dormindo com olhos fechados e Zzz subindo
Dormindo, os rostos novos mostram os olhos como tracos (-) e tres Z de tamanhos diferentes saem do canto do olho direito, sobem crescendo e somem em ciclo. Na Matriz a boca vira '_' (- _ -) e os Z sao maiores, em LEDs. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -453,7 +453,10 @@ function tracosDoRosto(esc) {
|
||||
const tracos = [];
|
||||
if (EXTRAS.boca) {
|
||||
const forma = r.boca;
|
||||
tracos.push({ d: caminhoBoca(forma), largura: BOCA_L * 0.18, cheio: forma === "aberta" });
|
||||
if (r.dormindo) { // dormindo na Matriz: "– _ –"
|
||||
const cx = BOCA[0], cy = BOCA[1] + deslocamentoBoca() + BOCA_L * 0.08, l = BOCA_L * 0.32;
|
||||
tracos.push({ d: 'M ' + (cx - l) + ',' + cy + ' L ' + (cx + l) + ',' + cy, largura: BOCA_L * 0.16 });
|
||||
} else tracos.push({ d: caminhoBoca(forma), largura: BOCA_L * 0.18, cheio: forma === "aberta" });
|
||||
}
|
||||
if (EXTRAS.sobrancelhas && !r.dormindo) {
|
||||
[E1, E2].forEach((c, i) => {
|
||||
|
||||
@@ -118,6 +118,11 @@
|
||||
const h = est.h * p.ry * respira * abre * (1 - amassa * 0.6);
|
||||
const x = p.cx - w / 2, y = p.cy - h / 2;
|
||||
c.fillStyle = css(o.cor);
|
||||
if (o.dormindo && !temConteudo) { // dormindo: "–" (olho fechado)
|
||||
const esp = Math.max(2, p.ry * 0.2);
|
||||
caixa(c, p.cx - w * 0.5, p.cy + h * 0.08 - esp / 2, w, esp, esp / 2); c.fill();
|
||||
return;
|
||||
}
|
||||
if (e.coracao > 0.5) { coracao(c, p.cx, p.cy, Math.min(w, h) * 0.55 * respira); return; }
|
||||
caixa(c, x, y, w, h, est.r * p.ry * respira);
|
||||
c.fill();
|
||||
@@ -227,6 +232,7 @@
|
||||
if (traco.cheio) bctx.fill(caminho); else bctx.stroke(caminho);
|
||||
}
|
||||
desenharMaos(bctx, o, olhos, tela.height / d);
|
||||
desenharZzz(bctx, o, olhos, 1.6); // em LEDs o Z precisa ser maior para ler
|
||||
bctx.restore();
|
||||
const px = bctx.getImageData(0, 0, colunas, linhas).data;
|
||||
ctx.fillStyle = '#000'; ctx.fillRect(0, 0, tela.width, tela.height);
|
||||
@@ -266,10 +272,12 @@
|
||||
} else if (estilo.lente) {
|
||||
olhos.forEach((p, i) => olhoLente(ctx, o, p, estilo, estado[i]));
|
||||
desenharMaos(ctx, o, olhos, tela.height);
|
||||
desenharZzz(ctx, o, olhos);
|
||||
} else {
|
||||
cctx.clearRect(0, 0, camada.width, camada.height);
|
||||
olhos.forEach((p, i) => olhoPlano(cctx, o, p, estilo, estado[i]));
|
||||
desenharMaos(cctx, o, olhos, tela.height);
|
||||
desenharZzz(cctx, o, olhos);
|
||||
ctx.save();
|
||||
if (estilo.brilho) { ctx.shadowColor = css(o.cor, 0.7); ctx.shadowBlur = Math.min(60, tela.height * 0.05); }
|
||||
ctx.drawImage(camada, 0, 0);
|
||||
@@ -388,6 +396,28 @@
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------ Zzz
|
||||
function desenharZzz(c, o, olhos, fator) {
|
||||
fator = fator || 1;
|
||||
if (!o.dormindo) return;
|
||||
const d = olhos.slice().sort((a, b) => a.cx - b.cx)[1]; // olho da direita na tela
|
||||
const x0 = d.cx + d.ry * 0.7, y0 = d.cy - d.ry * 0.55;
|
||||
c.save();
|
||||
c.strokeStyle = css(o.cor); c.lineCap = 'round'; c.lineJoin = 'round';
|
||||
for (let i = 0; i < 3; i++) {
|
||||
const k = ((o.t || 0) * 0.32 + i / 3) % 1; // cada Z num ponto do ciclo
|
||||
const tam = d.ry * (0.28 + 0.3 * k) * fator;
|
||||
const x = x0 + d.ry * 0.7 * k + Math.sin(k * Math.PI * 2) * d.ry * 0.08, y = y0 - d.ry * 1.7 * k;
|
||||
c.globalAlpha = Math.min(1, k / 0.15) * (1 - k);
|
||||
c.lineWidth = Math.max(1.5, tam * 0.2);
|
||||
c.beginPath();
|
||||
c.moveTo(x - tam / 2, y - tam / 2); c.lineTo(x + tam / 2, y - tam / 2);
|
||||
c.lineTo(x - tam / 2, y + tam / 2); c.lineTo(x + tam / 2, y + tam / 2);
|
||||
c.stroke();
|
||||
}
|
||||
c.restore();
|
||||
}
|
||||
|
||||
// --------------------------------------------------------- faixa de baixo
|
||||
// A parte de baixo da tela vira palco: legenda da conversa, pensando, equalizador e carga.
|
||||
const faixa = { modo: null, texto: '', t0: null, dur: 0 };
|
||||
|
||||
Reference in New Issue
Block a user