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 = [];
|
const tracos = [];
|
||||||
if (EXTRAS.boca) {
|
if (EXTRAS.boca) {
|
||||||
const forma = r.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) {
|
if (EXTRAS.sobrancelhas && !r.dormindo) {
|
||||||
[E1, E2].forEach((c, i) => {
|
[E1, E2].forEach((c, i) => {
|
||||||
|
|||||||
@@ -118,6 +118,11 @@
|
|||||||
const h = est.h * p.ry * respira * abre * (1 - amassa * 0.6);
|
const h = est.h * p.ry * respira * abre * (1 - amassa * 0.6);
|
||||||
const x = p.cx - w / 2, y = p.cy - h / 2;
|
const x = p.cx - w / 2, y = p.cy - h / 2;
|
||||||
c.fillStyle = css(o.cor);
|
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; }
|
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);
|
caixa(c, x, y, w, h, est.r * p.ry * respira);
|
||||||
c.fill();
|
c.fill();
|
||||||
@@ -227,6 +232,7 @@
|
|||||||
if (traco.cheio) bctx.fill(caminho); else bctx.stroke(caminho);
|
if (traco.cheio) bctx.fill(caminho); else bctx.stroke(caminho);
|
||||||
}
|
}
|
||||||
desenharMaos(bctx, o, olhos, tela.height / d);
|
desenharMaos(bctx, o, olhos, tela.height / d);
|
||||||
|
desenharZzz(bctx, o, olhos, 1.6); // em LEDs o Z precisa ser maior para ler
|
||||||
bctx.restore();
|
bctx.restore();
|
||||||
const px = bctx.getImageData(0, 0, colunas, linhas).data;
|
const px = bctx.getImageData(0, 0, colunas, linhas).data;
|
||||||
ctx.fillStyle = '#000'; ctx.fillRect(0, 0, tela.width, tela.height);
|
ctx.fillStyle = '#000'; ctx.fillRect(0, 0, tela.width, tela.height);
|
||||||
@@ -266,10 +272,12 @@
|
|||||||
} else if (estilo.lente) {
|
} else if (estilo.lente) {
|
||||||
olhos.forEach((p, i) => olhoLente(ctx, o, p, estilo, estado[i]));
|
olhos.forEach((p, i) => olhoLente(ctx, o, p, estilo, estado[i]));
|
||||||
desenharMaos(ctx, o, olhos, tela.height);
|
desenharMaos(ctx, o, olhos, tela.height);
|
||||||
|
desenharZzz(ctx, o, olhos);
|
||||||
} else {
|
} else {
|
||||||
cctx.clearRect(0, 0, camada.width, camada.height);
|
cctx.clearRect(0, 0, camada.width, camada.height);
|
||||||
olhos.forEach((p, i) => olhoPlano(cctx, o, p, estilo, estado[i]));
|
olhos.forEach((p, i) => olhoPlano(cctx, o, p, estilo, estado[i]));
|
||||||
desenharMaos(cctx, o, olhos, tela.height);
|
desenharMaos(cctx, o, olhos, tela.height);
|
||||||
|
desenharZzz(cctx, o, olhos);
|
||||||
ctx.save();
|
ctx.save();
|
||||||
if (estilo.brilho) { ctx.shadowColor = css(o.cor, 0.7); ctx.shadowBlur = Math.min(60, tela.height * 0.05); }
|
if (estilo.brilho) { ctx.shadowColor = css(o.cor, 0.7); ctx.shadowBlur = Math.min(60, tela.height * 0.05); }
|
||||||
ctx.drawImage(camada, 0, 0);
|
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
|
// --------------------------------------------------------- faixa de baixo
|
||||||
// A parte de baixo da tela vira palco: legenda da conversa, pensando, equalizador e carga.
|
// A parte de baixo da tela vira palco: legenda da conversa, pensando, equalizador e carga.
|
||||||
const faixa = { modo: null, texto: '', t0: null, dur: 0 };
|
const faixa = { modo: null, texto: '', t0: null, dur: 0 };
|
||||||
|
|||||||
+4
-1
@@ -453,7 +453,10 @@ function tracosDoRosto(esc) {
|
|||||||
const tracos = [];
|
const tracos = [];
|
||||||
if (EXTRAS.boca) {
|
if (EXTRAS.boca) {
|
||||||
const forma = r.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) {
|
if (EXTRAS.sobrancelhas && !r.dormindo) {
|
||||||
[E1, E2].forEach((c, i) => {
|
[E1, E2].forEach((c, i) => {
|
||||||
|
|||||||
@@ -118,6 +118,11 @@
|
|||||||
const h = est.h * p.ry * respira * abre * (1 - amassa * 0.6);
|
const h = est.h * p.ry * respira * abre * (1 - amassa * 0.6);
|
||||||
const x = p.cx - w / 2, y = p.cy - h / 2;
|
const x = p.cx - w / 2, y = p.cy - h / 2;
|
||||||
c.fillStyle = css(o.cor);
|
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; }
|
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);
|
caixa(c, x, y, w, h, est.r * p.ry * respira);
|
||||||
c.fill();
|
c.fill();
|
||||||
@@ -227,6 +232,7 @@
|
|||||||
if (traco.cheio) bctx.fill(caminho); else bctx.stroke(caminho);
|
if (traco.cheio) bctx.fill(caminho); else bctx.stroke(caminho);
|
||||||
}
|
}
|
||||||
desenharMaos(bctx, o, olhos, tela.height / d);
|
desenharMaos(bctx, o, olhos, tela.height / d);
|
||||||
|
desenharZzz(bctx, o, olhos, 1.6); // em LEDs o Z precisa ser maior para ler
|
||||||
bctx.restore();
|
bctx.restore();
|
||||||
const px = bctx.getImageData(0, 0, colunas, linhas).data;
|
const px = bctx.getImageData(0, 0, colunas, linhas).data;
|
||||||
ctx.fillStyle = '#000'; ctx.fillRect(0, 0, tela.width, tela.height);
|
ctx.fillStyle = '#000'; ctx.fillRect(0, 0, tela.width, tela.height);
|
||||||
@@ -266,10 +272,12 @@
|
|||||||
} else if (estilo.lente) {
|
} else if (estilo.lente) {
|
||||||
olhos.forEach((p, i) => olhoLente(ctx, o, p, estilo, estado[i]));
|
olhos.forEach((p, i) => olhoLente(ctx, o, p, estilo, estado[i]));
|
||||||
desenharMaos(ctx, o, olhos, tela.height);
|
desenharMaos(ctx, o, olhos, tela.height);
|
||||||
|
desenharZzz(ctx, o, olhos);
|
||||||
} else {
|
} else {
|
||||||
cctx.clearRect(0, 0, camada.width, camada.height);
|
cctx.clearRect(0, 0, camada.width, camada.height);
|
||||||
olhos.forEach((p, i) => olhoPlano(cctx, o, p, estilo, estado[i]));
|
olhos.forEach((p, i) => olhoPlano(cctx, o, p, estilo, estado[i]));
|
||||||
desenharMaos(cctx, o, olhos, tela.height);
|
desenharMaos(cctx, o, olhos, tela.height);
|
||||||
|
desenharZzz(cctx, o, olhos);
|
||||||
ctx.save();
|
ctx.save();
|
||||||
if (estilo.brilho) { ctx.shadowColor = css(o.cor, 0.7); ctx.shadowBlur = Math.min(60, tela.height * 0.05); }
|
if (estilo.brilho) { ctx.shadowColor = css(o.cor, 0.7); ctx.shadowBlur = Math.min(60, tela.height * 0.05); }
|
||||||
ctx.drawImage(camada, 0, 0);
|
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
|
// --------------------------------------------------------- faixa de baixo
|
||||||
// A parte de baixo da tela vira palco: legenda da conversa, pensando, equalizador e carga.
|
// A parte de baixo da tela vira palco: legenda da conversa, pensando, equalizador e carga.
|
||||||
const faixa = { modo: null, texto: '', t0: null, dur: 0 };
|
const faixa = { modo: null, texto: '', t0: null, dur: 0 };
|
||||||
|
|||||||
Reference in New Issue
Block a user